| SourceCode/Bond/Servo/PageRecipe.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/Servo/PageRecipe.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/Servo/RecipeDeviceBindDlg.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/Servo/RecipeManager.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/Servo/RecipeManager.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/Servo/Servo.rc | 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/Servo/resource.h | 补丁 | 查看 | 原始文档 | blame | 历史 |
SourceCode/Bond/Servo/PageRecipe.cpp
@@ -6,7 +6,7 @@ #include "afxdialogex.h" #include "PageRecipe.h" #include "MsgDlg.h" #include "RecipeDeviceBindDlg.h" // CPageRecipe 对话框 @@ -20,6 +20,60 @@ CPageRecipe::~CPageRecipe() { } void CPageRecipe::UpdateRecipeByPPID(const CString& strPPID) { if (strPPID.IsEmpty()) { AfxMessageBox(_T("请选择一个配方!")); return; } auto& mgr = RecipeManager::getInstance(); // 查询选中配方的详细数据 std::string oldPPID = CT2A(strPPID); RecipeInfo oldRecipe = mgr.getRecipeByPPID(oldPPID); if (oldRecipe.strPPID.empty()) { AfxMessageBox(_T("获取配方数据失败!")); return; } // 弹出编辑对话框,并初始化为当前内容 CRecipeDeviceBindDlg dlg(this); dlg.SetRecipeInfo(oldRecipe); if (dlg.DoModal() == IDOK) { const RecipeInfo& newRecipe = dlg.GetRecipeInfo(); bool success = false; // 判断PPID是否有改动 if (oldRecipe.strPPID != newRecipe.strPPID) { // 先更新PPID,再整体更新内容 if (mgr.updatePPID(oldRecipe.strPPID, newRecipe.strPPID)) { success = mgr.updateRecipe(newRecipe); if (!success) { AfxMessageBox(_T("已更改PPID,但更新配方内容失败,请检查日志")); } } else { AfxMessageBox(_T("更新PPID失败,请检查日志")); return; } } else { // 只更新内容 success = mgr.updateRecipe(newRecipe); if (!success) { AfxMessageBox(_T("更新配方失败,请检查日志")); } } if (success) { auto vecData = mgr.getAllRecipes(); FillDataToListCtrl(vecData); } } } void CPageRecipe::FillDataToListCtrl(const std::vector<RecipeInfo>& vecRecipe) { @@ -64,7 +118,6 @@ return; } // 遍历数据并插入到CListCtrl中 std::map<int, short>& ids = pList->getIds(); for (auto item : ids) { @@ -87,15 +140,16 @@ BEGIN_MESSAGE_MAP(CPageRecipe, CDialogEx) ON_WM_SIZE() ON_WM_DESTROY() ON_WM_SHOWWINDOW() ON_BN_CLICKED(IDC_BUTTON_NEW, &CPageRecipe::OnBnClickedButtonNew) ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageRecipe::OnBnClickedButtonSearch) ON_BN_CLICKED(IDC_BUTTON_MODIFY, &CPageRecipe::OnBnClickedButtonModify) ON_BN_CLICKED(IDC_BUTTON_DELETE, &CPageRecipe::OnBnClickedButtonDelete) ON_BN_CLICKED(IDC_BUTTON_DELETE_ALL, &CPageRecipe::OnBnClickedButtonDeleteAll) ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CPageRecipe::OnBnClickedButtonRefresh) ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PPID, &CPageRecipe::OnLvnItemChangedListPPID) ON_WM_DESTROY() ON_CBN_SELCHANGE(IDC_COMBO_EQUIPMENT, &CPageRecipe::OnCbnSelchangeComboEquipment) ON_WM_SHOWWINDOW() END_MESSAGE_MAP() @@ -172,9 +226,10 @@ // 按钮竖直排列在右侧 CWnd* buttons[] = { GetDlgItem(IDC_BUTTON_REFRESH), GetDlgItem(IDC_BUTTON_NEW), GetDlgItem(IDC_BUTTON_MODIFY), GetDlgItem(IDC_BUTTON_DELETE), GetDlgItem(IDC_BUTTON_DELETE_ALL), GetDlgItem(IDC_BUTTON_MODIFY) GetDlgItem(IDC_BUTTON_DELETE_ALL) }; for (auto pBtn : buttons) { @@ -185,74 +240,130 @@ } } void CPageRecipe::OnDestroy() { CDialogEx::OnDestroy(); // 保存列宽 CString strIniFile, strItem, strTemp; strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); CHeaderCtrl* pHeader = m_listPPID.GetHeaderCtrl(); for (int i = 0; i < pHeader->GetItemCount(); i++) { RECT rect; pHeader->GetItemRect(i, &rect); strItem.Format(_T("Col_%d_Width"), i); strTemp.Format(_T("%d"), rect.right - rect.left); WritePrivateProfileString("PageRecipeListCtrl", strItem, strTemp, strIniFile); } } void CPageRecipe::OnShowWindow(BOOL bShow, UINT nStatus) { CDialogEx::OnShowWindow(bShow, nStatus); if (bShow) { CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); if (pComboBox->GetCount() == 0) { SERVO::CMaster& master = theApp.m_model.getMaster(); SERVO::CEquipment* pEq[] = { nullptr, master.getEquipment(EQ_ID_EFEM), master.getEquipment(EQ_ID_Bonder1), master.getEquipment(EQ_ID_Bonder2), master.getEquipment(EQ_ID_BAKE_COOLING), master.getEquipment(EQ_ID_VACUUMBAKE), master.getEquipment(EQ_ID_MEASUREMENT), }; CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); for (int i = 0; i < sizeof(pEq) / sizeof(pEq[0]); i++) { pComboBox->InsertString(i, pEq[i] == nullptr ? _T("Master") : pEq[i]->getName().c_str()); pComboBox->SetItemDataPtr(i, pEq[i]); } pComboBox->SetCurSel(0); } } } void CPageRecipe::OnBnClickedButtonNew() { // TODO: 在此添加控件通知处理程序代码 //CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); //int nSel = pComboBox->GetCurSel(); //SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nSel); //if (pEq == nullptr) { // return; //} CRecipeDeviceBindDlg dlg(this); if (dlg.DoModal() == IDOK) { const RecipeInfo& newRecipe = dlg.GetRecipeInfo(); auto& mgr = RecipeManager::getInstance(); if (mgr.ppidExists(newRecipe.strPPID)) { // 已存在,询问是否覆盖 int ret = AfxMessageBox(_T("该 PPID 已存在,是否覆盖原配方?"), MB_YESNO | MB_ICONQUESTION); if (ret == IDYES) { if (mgr.updateRecipe(newRecipe)) { auto vecData = mgr.getAllRecipes(); FillDataToListCtrl(vecData); } else { AfxMessageBox(_T("更新配方失败,请检查日志")); } } } else { // 不存在,直接新增 if (mgr.addRecipe(newRecipe)) { auto vecData = mgr.getAllRecipes(); FillDataToListCtrl(vecData); } else { AfxMessageBox(_T("添加配方失败,请检查日志")); } } } } void CPageRecipe::OnBnClickedButtonSearch() { CString strKeyword; GetDlgItemText(IDC_EDIT_KEYWORD, strKeyword); AfxMessageBox(strKeyword); strKeyword.Trim(); std::vector<RecipeInfo> vecData; if (strKeyword.IsEmpty()) { // 关键词为空,显示全部配方 vecData = RecipeManager::getInstance().getAllRecipes(); } else { // 根据关键词搜索配方 vecData = RecipeManager::getInstance().getRecipesByKeyword(std::string(CT2A(strKeyword))); } // 如果没有数据,弹出提示 if (vecData.empty()) { AfxMessageBox(_T("未找到匹配的配方!")); return; } FillDataToListCtrl(vecData); } void CPageRecipe::OnBnClickedButtonModify() { // TODO: 在此添加控件通知处理程序代码 /* POSITION pos = m_listPPID.GetFirstSelectedItemPosition(); if (!pos) { AfxMessageBox(_T("请选择要修改的配方")); AfxMessageBox(_T("请先选择一条配方记录进行修改!")); return; } int nSel = m_listPPID.GetNextSelectedItem(pos); CString strOldPPID = m_listPPID.GetItemText(nSel, 2); CString strOldDesc = m_listPPID.GetItemText(nSel, 3); CString strNewPPID, strNewDesc; m_editPPID.GetWindowText(strNewPPID); m_editDesc.GetWindowText(strNewDesc); // 判空 if (strOldPPID.IsEmpty() || strNewPPID.IsEmpty()) { AfxMessageBox(_T("PPID 不能为空")); return; } std::string oldPPID = CT2A(strOldPPID); std::string newPPID = CT2A(strNewPPID); std::string newDesc = CT2A(strNewDesc); bool bPPIDChanged = (strOldPPID.Compare(strNewPPID) != 0); bool bDescChanged = (strOldDesc.Compare(strNewDesc) != 0); if (!bPPIDChanged && !bDescChanged) { return; } if (bPPIDChanged) { // 新 PPID 不可重复 if (RecipeManager::getInstance().ppidExists(newPPID)) { AfxMessageBox(_T("新 PPID 已存在,请使用其他值")); return; } // 调用 updatePPID,同时更新描述 if (RecipeManager::getInstance().updatePPID(oldPPID, newPPID)) { m_listPPID.SetItemText(nSel, 2, strNewPPID); } else { AfxMessageBox(_T("更新失败,请检查日志")); } } if (bDescChanged) { // 更新描述 if (RecipeManager::getInstance().updateDescription(oldPPID, newDesc)) { m_listPPID.SetItemText(nSel, 3, strNewDesc); } else { AfxMessageBox(_T("描述更新失败")); } } */ CString strPPID = m_listPPID.GetItemText(nSel, 2); UpdateRecipeByPPID(strPPID); } void CPageRecipe::OnBnClickedButtonDelete() @@ -376,56 +487,5 @@ else { SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); FillRecipeListToListCtrl(pRecipeList); } } void CPageRecipe::OnDestroy() { CDialogEx::OnDestroy(); // 保存列宽 CString strIniFile, strItem, strTemp; strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); CHeaderCtrl* pHeader = m_listPPID.GetHeaderCtrl(); for (int i = 0; i < pHeader->GetItemCount(); i++) { RECT rect; pHeader->GetItemRect(i, &rect); strItem.Format(_T("Col_%d_Width"), i); strTemp.Format(_T("%d"), rect.right - rect.left); WritePrivateProfileString("PageRecipeListCtrl", strItem, strTemp, strIniFile); } } void CPageRecipe::OnShowWindow(BOOL bShow, UINT nStatus) { CDialogEx::OnShowWindow(bShow, nStatus); if (bShow) { CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); if (pComboBox->GetCount() == 0) { SERVO::CMaster& master = theApp.m_model.getMaster(); SERVO::CEquipment* pEq[] = { nullptr, master.getEquipment(EQ_ID_EFEM), master.getEquipment(EQ_ID_Bonder1), master.getEquipment(EQ_ID_Bonder2), master.getEquipment(EQ_ID_BAKE_COOLING), master.getEquipment(EQ_ID_VACUUMBAKE), master.getEquipment(EQ_ID_MEASUREMENT), }; CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); for (int i = 0; i < sizeof(pEq) / sizeof(pEq[0]); i++) { pComboBox->InsertString(i, pEq[i] == nullptr ? _T("Master") : pEq[i]->getName().c_str()); pComboBox->SetItemDataPtr(i, pEq[i]); } pComboBox->SetCurSel(0); } } } SourceCode/Bond/Servo/PageRecipe.h
@@ -13,6 +13,7 @@ virtual ~CPageRecipe(); private: void UpdateRecipeByPPID(const CString& strPPID); void FillDataToListCtrl(const std::vector<RecipeInfo>& vecRecipe); void FillRecipeListToListCtrl(SERVO::CRecipeList* pList); @@ -25,18 +26,18 @@ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 virtual BOOL OnInitDialog(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnDestroy(); afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); afx_msg void OnBnClickedButtonNew(); afx_msg void OnBnClickedButtonSearch(); afx_msg void OnBnClickedButtonModify(); afx_msg void OnBnClickedButtonDelete(); afx_msg void OnBnClickedButtonDeleteAll(); afx_msg void OnBnClickedButtonRefresh(); afx_msg void OnLvnItemChangedListPPID(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnCbnSelchangeComboEquipment(); DECLARE_MESSAGE_MAP() private: CListCtrl m_listPPID; public: afx_msg void OnDestroy(); afx_msg void OnCbnSelchangeComboEquipment(); afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); }; SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
@@ -28,6 +28,8 @@ CRecipeDeviceBindDlg::CRecipeDeviceBindDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_DIALOG_RECIPE_DEVICE_BIND, pParent) , m_strPPID(_T("")) , m_strDesc(_T("")) { } @@ -36,15 +38,26 @@ { } void CRecipeDeviceBindDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); const RecipeInfo& CRecipeDeviceBindDlg::GetRecipeInfo() const { return m_recipe; } void CRecipeDeviceBindDlg::SetRecipeInfo(const RecipeInfo& info) { m_recipe = info; } void CRecipeDeviceBindDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_PPID, m_strPPID); DDX_Text(pDX, IDC_EDIT_DESC, m_strDesc); } BEGIN_MESSAGE_MAP(CRecipeDeviceBindDlg, CDialogEx) ON_WM_CLOSE() ON_WM_SIZE() ON_BN_CLICKED(IDOK, &CRecipeDeviceBindDlg::OnBnClickedOk) END_MESSAGE_MAP() @@ -54,42 +67,74 @@ { CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 // 设置固定大小(例如 600x400) SetWindowPos(nullptr, 0, 0, 600, 400, SWP_NOMOVE | SWP_NOZORDER); // TODO: 在此添加额外的初始化 if (m_recipe.vecDeviceList.empty()) { SetWindowText(_T("新建配方")); // 创建控件 const int totalControlWidth = 340; CRect clientRect; GetClientRect(&clientRect); int xStart = (clientRect.Width() - totalControlWidth) / 2; // 设置固定大小(例如 600x400) SetWindowPos(nullptr, 0, 0, 600, 400, SWP_NOMOVE | SWP_NOZORDER); const int nRowHeight = 30; const int yStart = 30; // 顶部起始高度 // 创建控件 const int totalControlWidth = 340; CRect clientRect; GetClientRect(&clientRect); int xStart = (clientRect.Width() - totalControlWidth) / 2; const int nRowCount = static_cast<int>(g_vecBindDevices.size()); for (int i = 0; i < nRowCount; ++i) { int y = yStart + i * nRowHeight; const auto& meta = g_vecBindDevices[i]; const int nRowHeight = 30; const int yStart = 30; // 顶部起始高度 CEdit* pEditID = new CEdit(); pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(xStart, y, xStart + 100, y + 25), this, IDC_EDIT_DEVICEID_BASE + i); const int nRowCount = static_cast<int>(g_vecBindDevices.size()); for (int i = 0; i < nRowCount; ++i) { int y = yStart + i * nRowHeight; const auto& meta = g_vecBindDevices[i]; CString strID; strID.Format(_T("%d"), meta.nDeviceID); pEditID->SetWindowText(strID); pEditID->SetReadOnly(TRUE); // 设备ID只读 CEdit* pEditID = new CEdit(); pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(xStart, y, xStart + 100, y + 25), this, IDC_EDIT_DEVICEID_BASE + i); CEdit* pEditName = new CEdit(); pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(xStart + 110, y, xStart + 210, y + 25), this, IDC_EDIT_DEVICENAME_BASE + i); pEditName->SetWindowText(CA2T(meta.strDeviceName)); pEditName->SetReadOnly(TRUE); // 设备名称只读 CString strID; strID.Format(_T("%d"), meta.nDeviceID); pEditID->SetWindowText(strID); pEditID->SetReadOnly(TRUE); // 设备ID只读 CComboBox* pCombo = new CComboBox(); pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(xStart + 220, y, xStart + 340, y + 300), this, IDC_COMBO_RECIPEID_BASE + i); CEdit* pEditName = new CEdit(); pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(xStart + 110, y, xStart + 210, y + 25), this, IDC_EDIT_DEVICENAME_BASE + i); pEditName->SetWindowText(CA2T(meta.strDeviceName)); pEditName->SetReadOnly(TRUE); // 设备名称只读 // 添加选项到 ComboBox m_vecDevices.push_back({ pEditID, pEditName, pCombo }); CComboBox* pCombo = new CComboBox(); pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(xStart + 220, y, xStart + 340, y + 300), this, IDC_COMBO_RECIPEID_BASE + i); // 添加选项到 ComboBox m_vecDevices.push_back({ pEditID, pEditName, pCombo }); } } else { SetWindowText(_T("编辑配方")); m_strPPID = CA2T(m_recipe.strPPID.c_str()); m_strDesc = CA2T(m_recipe.strDescription.c_str()); UpdateData(FALSE); // 设置设备行数据 for (size_t i = 0; i < m_recipe.vecDeviceList.size() && i < m_vecDevices.size(); ++i) { const DeviceRecipe& d = m_recipe.vecDeviceList[i]; CString str; // 设置设备ID和名称 str.Format(_T("%d"), d.nDeviceID); m_vecDevices[i].editDeviceID->SetWindowText(str); str.Format(_T("%s"), d.strDeviceName.c_str()); m_vecDevices[i].editDeviceName->SetWindowText(str); /*ComboBox选择配方ID,后面需要修改****/ //int nCount = m_vecDevices[i].comboRecipeID->GetCount(); //for (int idx = 0; idx < nCount; ++idx) { // if ((int)m_vecDevices[i].comboRecipeID->GetItemData(idx) == d.nRecipeID) { // m_vecDevices[i].comboRecipeID->SetCurSel(idx); // break; // } //} } } return TRUE; // return TRUE unless you set the focus to a control @@ -124,4 +169,41 @@ CDialogEx::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 } } void CRecipeDeviceBindDlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); // 收集所有设备映射 m_recipe.vecDeviceList.clear(); for (const auto& dev : m_vecDevices) { DeviceRecipe info; CString strID, strName; dev.editDeviceID->GetWindowText(strID); dev.editDeviceName->GetWindowText(strName); int sel = dev.comboRecipeID->GetCurSel(); info.nRecipeID = -1; if (sel != CB_ERR) { info.nRecipeID = (int)dev.comboRecipeID->GetItemData(sel); } info.nDeviceID = _ttoi(strID); info.strDeviceName = CT2A(strName); m_recipe.vecDeviceList.push_back(info); } // 检查 PPID 是否为空 if (m_strPPID.IsEmpty()) { AfxMessageBox(_T("配方 PPID 不能为空")); return; } // PPID和描述 m_recipe.strPPID = CT2A(m_strPPID); m_recipe.strDescription = CT2A(m_strDesc); CDialogEx::OnOK(); } SourceCode/Bond/Servo/RecipeDeviceBindDlg.h
@@ -1,6 +1,6 @@ #pragma once #include "afxdialogex.h" #include "RecipeManager.h" // CRecipeDeviceBindDlg 对话框 @@ -12,6 +12,9 @@ CRecipeDeviceBindDlg(CWnd* pParent = nullptr); // 标准构造函数 virtual ~CRecipeDeviceBindDlg(); const RecipeInfo& GetRecipeInfo() const; void SetRecipeInfo(const RecipeInfo& info); // 对话框数据 #ifdef AFX_DESIGN_TIME enum { IDD = IDD_DIALOG_RECIPE_DEVICE_BIND }; @@ -22,6 +25,7 @@ virtual BOOL OnInitDialog(); afx_msg void OnClose(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnBnClickedOk(); DECLARE_MESSAGE_MAP() private: @@ -31,5 +35,8 @@ CComboBox* comboRecipeID; }; CString m_strPPID; CString m_strDesc; RecipeInfo m_recipe; std::vector<DeviceWidget> m_vecDevices; }; SourceCode/Bond/Servo/RecipeManager.cpp
@@ -220,7 +220,6 @@ for (const auto& dev : devs) { DeviceRecipe dr; dr.strPPID = info.strPPID; try { dr.nDeviceID = std::stoi(dev[0]); dr.strDeviceName = dev[1]; @@ -294,7 +293,6 @@ auto devs = m_pDB->fetchResults("SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" + ppid + "';"); for (const auto& dev : devs) { DeviceRecipe dr; dr.strPPID = ppid; try { dr.nDeviceID = std::stoi(dev[0]); dr.strDeviceName = dev[1]; @@ -448,8 +446,8 @@ recipe.strDescription = "Main Board Burn-in"; recipe.vecDeviceList = { {1, 101, "P1001","Burner A"}, {2, 102, "P1001", "Burner B"} {1, 101, "Burner A"}, {2, 102, "Burner B"} }; addRecipe(recipe); @@ -486,7 +484,6 @@ std::getline(ss, description, ','); std::getline(ss, createTime, ','); dev.strPPID = ppid; auto& recipe = recipeMap[ppid]; recipe.strPPID = ppid; recipe.strDescription = description; SourceCode/Bond/Servo/RecipeManager.h
@@ -10,8 +10,7 @@ // 单个设备配方映射信息 struct DeviceRecipe { int nDeviceID; // 设备ID int nRecipeID; // 该设备对应的子配方ID std::string strPPID; // 配方ID(主键) int nRecipeID; // 子配方ID std::string strDeviceName; // 设备名称 }; SourceCode/Bond/Servo/Servo.rcBinary files differ
SourceCode/Bond/Servo/resource.hBinary files differ