Вопрос конкретно людям отлично знающим дельфи.
Есть проект, его суть автоматизация поверки компараторов (сверхточных весов) массы.
Для общения с компараторами есть библиотека, отлаженная, сто процентов рабочая (проверенная временем в других проектах).
Так же, есть эмулятор компаратора.
Пред-история: Поверка может проводиться по одной из трех схем измерений, для каждой схемы, свой вид таблицы конечных результатов, так как, ни один компонент типа Grid не удовлетворил моих потребностей, я написал свой, для отображения этих таблиц. Все работало хорошо, компаратор определялся, получал данные взвешивания, никаких проблем не наблюдалось во всей программе, кроме одного но, программа падала при завершении, причиной тому было, неправильная работа, или неправильная связь компонента с датасоурсом, и эту проблему мне так и не удалось решить, тогда я взял код компонента, и вынес его прямо в форму измерений. Проблема соответственно исчезла.
Но появилась другая, и не на форме измерений, а в любых точках программы, где устанавливается связь с компаратором, связь устанавливается на ура, но вот возвращает вместо серийного номера и модели - текущий вес.
Я ничего не менял в программе, за исключением удаления из проекта ссылок на файл бывшего компонента, и переноса из файла компонента в другой но похожий по логике модуль uComparators.
Код:
const
CCompUnitType:array [0..3] of string = ('kg','g','mg','mkg');
CUnitType:array [0..3] of string = ('кг','г','мг','мкг');
Соответственно, везде в uses заменил имя модуля компонента на uComparators, где его не хватало.
Все хорошо компилируется, сборку собирал с полной пере-компиляцией на разных машинах, результат один и тот же. В предыдущей версии все норм отрабатывает, в новой нет. При том, эмулятор возвращает правильно серийный номер и модель, а компаратор нет.
Для связи с весами, во всех точках программы используется функция:
Код:
function TDM.CheckScale(ConnectStr: ansistring; var edSN, edModel: ansistring): integer;
var
bOk: Boolean;
hScales: HWND;
nRet: Integer;
nAct: DWORD;
arBuffer: tBuffer;
begin
hScales := ScalesCreateInterface(PAnsiChar('Sartorius\Common'), '');
ScalesSetupConnection(hScales, 1, PAnsiChar(ConnectStr));
bOk := True;
nRet := ScalesDirectQueryModelName(hScales, 2000, nAct, arBuffer, 64);
if RET_SCALES_OK = nRet then
edModel := StrPas(arBuffer)
else
begin
edModel := '';
bOk := False;
end;
if bOk = True then
begin
nRet := ScalesDirectQuerySerialNumber(hScales, 2000, nAct, arBuffer, 64);
if RET_SCALES_OK = nRet then
edSN := StrPas(arBuffer)
else
begin
edSN := '';
end;
end
else
begin
edSN := '';
end;
ScalesReleaseInterface(hScales);
CheckScale := nRet;
end;
На выходе из функции, в переменных edSN, edModel в старой версии имею серийный номер и модель, полученный с компаратора и эмулятора, а вот в новой, с компаратора получаю в обоих переменных текущий вес с компаратора а с эмулятора серийный номер и модель. ConnectStr - строка подключения к весам, на входе в функцию правильная.
Функция получения веса, во всех случаях работает правильно:
Код:
function TDM.GetWeight(ConnectStr: ansistring; var arWeight,
arUnit: String): integer;
var
hScales: HWND;
nLastQueryWeight: DWORD;
nRet: Integer;
nAct: DWORD;
nWeigthState: DWORD;
aFloatWeight: tBuffer;
aUnit: tBuffer;
bQuery: Boolean;
begin
inherited;
nRet := 0;
hScales := ScalesCreateInterface(PAnsiChar('Sartorius\Common'), '');
ScalesSetupConnection(hScales, 1, PAnsiChar(ConnectStr));
ScalesDirectClearBuffers(hScales);
nLastQueryWeight := GetTickCount();
bQuery := True;
while (nLastQueryWeight + 30000 > GetTickCount()) and (nRet <> RET_SCALES_OK) do
begin
if bQuery then
begin
ScalesDirectQueryWeight(hScales, 1);
bQuery := False;
end;
nRet := ScalesDirectWaitWeight(hScales, 50, nAct, aFloatWeight, 64, aUnit, 64, nWeigthState);
if RET_SCALES_OK = nRet then
begin
if WSTATE_STABLE = nWeigthState then
begin
arWeight:=String(aFloatWeight);
arUnit:=String(aUnit);
end
else
begin
nRet := 0;
bQuery := True;
end;
end;
end;
if nRet <> RET_SCALES_OK then
begin
arWeight:='';
arUnit:='';
end;
Result:=nRet;
ScalesReleaseInterface(hScales);
end;
Так же, в программе есть поиск компараторов, странно, но в случае поиска компараторов подключенных к компьютеру, серийный номер и модель возвращается во всех версиях правильно.
Код:
procedure TSysOptionsFrame.btnScaleEditClick(Sender: TObject);
var
tmpRec:Integer;
COMList:TStringList;
i,c:integer;
f:boolean;
zScaleSerial, ScaleType:AnsiString;
aw, au:String;
begin
if MessageDlg('Внимание, текущие настройки подключений будут переопределены, продолжить?', mtConfirmation, [mbOk, mbCancel], 0) = mrCancel then
exit;
WaitForm.ShowNow('Поиск компараторов');
_Delay(100);
SetEnableds(false);
with qryVwComs do
begin
DM.Comparators.Clear;
DisableControls;
tmpRec:=RecNo;
First;
//обновим список компараторов
while not Eof do
begin
DM.Comparators.Update(FieldByName('comparator_id').AsInteger, qryVwComsfactory_number.AsString, '',
AnsiString(FieldByName('com_settings').AsString),false, utMg);
Next;
end;
//получим список COM-портов
COMList:=DM.GetCOMList;
//ищем компараторы по COM-портам
if DM.Comparators.Count > 0 then
for I := 0 to DM.Comparators.Count - 1 do
with DM.Comparators.Comparators[i] do
if not Is_active then
begin
f:=false;
c:=0;
while (c < COMList.Count) and (not f) do
begin
DM.CheckScale(DM.GetConnectStr(COMList.Strings[c],String(COM)), zScaleSerial, ScaleType);
//здесь получаем правильные данные
if zScaleSerial <> '' then
if ScaleSerial = zScaleSerial then
begin
Port:=COMList.Strings[c];
Is_active:=true;
if DM.IsDebug then
DM.LogAdd('[Поиск компаратора '+ScaleSerial+'] '+DM.GetConnectStr(COMList.Strings[c],String(COM))+' - найден');
COMList.Delete(c);
f:=true;
if DM.GetWeight(DM.GetConnectStr(String(Port),String(COM)),aw, au) = RET_SCALES_OK then
WeightUnit:=TranslateUnitType(au);
end;
if DM.IsDebug and (not f) then
DM.LogAdd('[Поиск компаратора '+ScaleSerial+'] '+DM.GetConnectStr(COMList.Strings[c],String(COM)));
inc(c);
Application.ProcessMessages;
end;
end;
//обновляем
SetEnableds(true);
qryVwComs.Refresh;
RecNo:=tmpRec;
EnableControls;
//сохраняем
DM.Comparators.SaveToFile(ChangeFileExt(Application.ExeName,'.tcm'));
end;
COMList.Destroy;
WaitForm.Hide;
end;
Но вот в остальных точках программы, а именно на форме тестирования связи с компаратором и на форме измерения получаем вес в обе переменные вместо серийного номера и модели.
Код:
function TTestForm.IsConnect(var ScaleText: String): Integer;
var
nRet: integer;
begin
inherited;
nRet := DM.CheckScale(AnsiString(ConnectStr), ScaleSerial, ScaleType);
if ScaleSerial <> '' then
begin
nRet := 1;
ScaleText := 'Весы подключены.';
end
else
begin
if nRet = RET_SCALES_NO_PORT then
ScaleText := 'COM-порт недоступен!'
else
ScaleText := 'Нет ответа от весов!';
nRet := 0;
end;
IsConnect := nRet;
end;
Среда: CODE Gear RAD Studio 2009
Версия: 12.0.3420.21218
Обновления: Update3, Update4 (Database Pack Update)
ОС: XP SP3 //так же, компилировал и на Win7 с той же версией дельфи и обновлениями.
Скажу честно, уже голову сломал, а причину понять не могу, как две перенесенные строчки кода из одного модуля в другой, могли дать такой резонанс.
В понедельник поеду к заказчику, со средой дельфи, подскажите какие либо методики выявления такого рода ошибок, я с отладкой программ на ты, но в данном случае, не понимаю даже в какую сторону копать.
Буду признателен любой помощи, будут попутные вопросы задавайте.
Уж решения проблемы от вас не жду, но жду хотя бы хороших советов и наставлений.