Но вот недавно встала действительно нужная и важная задача - сделать GPS сервер для проверки разрабатываемого предприятием GPS-трекера.
Как работать с сокетными компонентами, уже разобрался (использую TServerSocket, Delphi 7).
А вот как вести обмен данными с самим трекером, не очень понятно.
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
18-05-2012 10:45
но при блокирующем режиме хотя бы нет проблемы слипания пакетов и мусора лишнего при приеме данных. - уверяю Вас, что эта проблема НАДУМАННАЯ!!! Что пришло в сокет - то и будет...ничего лишнего. У Вас есть четкое описание посылки от треккера. Там (100 пудов) есть четкое начало и четкий конец. И пусть там хоть 100 пакетов "слипнутся" - разблюдовать их пара пустяков. А проблему придумывают те, которые не хотят писать алгоритмы с асинхронной обработкой! Все вспоминают добрым словом DOS. Нет я не против DOS, но те приемы для многопоточных Виндов...ну жуть!
Сегодня вернулся все-таки к тому варианту, где сервер блокирующий.
Все не мог понять, как же ему правильно слать пакеты, трекер в упор не видел посылок от сервера. Вчера нашел на просторах сети, что лучше передавать записи (т.е. тип record) так - создать под пакет массив байтов, можно динамический, и наложить туда данные API-функцией CopyMemory.
Вот тогда-то наконец заработало. Разве что остается еще проблемка - трекер после того, как передаст некоторый набор данных, вдруг разрывает связь, а сервер от этого зависает. Но тут не знаю, разве сообщить об ошибке и разорвать связь со своей стороны, чтобы тупо не висеть.
Думаю, и в неблокирующем режиме тоже дело пойдет, но при блокирующем режиме хотя бы нет проблемы слипания пакетов и мусора лишнего при приеме данных. Поэтому и говорят, что его программировать проще.
Так вот, ответ не отправляется, в WireShark не видно, что что-то отправилось, вместо этого опять возникает OnClientRead. ...мдя-я-я... Вы конечно извините...но кроме как ... такое повествование никак назвать нельзя!!! Ну возник OnClientRead - ТАК ВЫ ПРОЧИТАЙТЕ ЧЕГО ТАМ!!! И ДЕЛАЙТЕ ВЫВОДЫ, а не сможете, то перескажите чего там Вы прочитали. Потому как если
1 Так вот вычитал я сначала заголовок (16 байт), потом вторым вызовом ReceiveBuf саму информационную часть (IMEI устройства - 15 байт). Тогда по идее дальше ничего на этот момент нет от трекера.
2. Он начнет передавать телеметрию только если ответишь на переданный IMEI (это ж handshake).
Тогда вот это - ответ не отправляется - БРЕХНЯ, потому что опять OnClientRead срабатывает.- т.е. "железяка" начинает отвечать, а она - дура, и работает только так, как ее запрограммировали (см. выше свое же).
Пробовал и из OnClientWrite слать ответ - то же самое.- конечно то же самое, потому что хэлп ЧИТАТЬ нужно! Это событие возникает гарантированно тогда, когда на попытку чего-то отправить - Вы получаете эксепшн WSAEWOULDBLOCK. В этом случае Вы должны успокоиться и еще раз попытаться отправить только при получении этого эвента. Поскольку Ваши посылки размером с гулькин ... - Вы в эту ситуацию не попадете никогда.
Попробовал я неблокирующий режим. Там дело еще хуже - принимаешь IMEI - ответ на него не отправляется.
Я там же, в OnClientRead после приема IMEI на него отвечаю.
Так вот, ответ не отправляется, в WireShark не видно, что что-то отправилось, вместо этого опять возникает OnClientRead.
Хочется понять, как это событие правильно использовать.
Как я понял, оно срабатывает, если в буфере есть данные.
Так вот вычитал я сначала заголовок (16 байт), потом вторым вызовом ReceiveBuf саму информационную часть (IMEI устройства - 15 байт). Тогда по идее дальше ничего на этот момент нет от трекера.
Он начнет передавать телеметрию только если ответишь на переданный IMEI (это ж handshake).
Так почему же ответ не отправляется, а опять OnClientRead срабатывает?
Пробовал и из OnClientWrite слать ответ - то же самое.
А у Вас планируются тысячи клиентов? Вы, простите, имеете лобби в каком-то министерстве? Типичный пример - циркуляры о комплектации чего-то исключительно чем-то. Мой Вам совет - отладтесь на TServerSocket в асинхронном режиме, особенно в части эвентов коннект/дисконнект/реад/еррор особенно с точки зрения потокобезопасности (никаких прямых вызовов экземпляров VCL и пр.). А потом, если у Вас действительно появятся такие тучи клиентов (а лучше до этого момента) спокойно напишете свой класс серверного сокета, в который и подсунете вот эти чуть подпедаленные обработчики. Примеры такого сокета есть у А.Григорьева на сайте, но лучше (я так сделал) купите его книгу. Я достаточно быстро написал свой класс клиента и сервера, но использую их только во вновь разрабатываемых приложениях. Старые как работали на TServer(Client)Socket-ах - так и работают... "Не трогай работающий код". ;-)
Ну да, как раз о том я и читал, что если TServerSocket в режиме stNonBlocking, то очень много клиентов (где-то так 1000-2000) нет смысла подключать - асинхронный сервер на ServerSocket загнется от такого.
Видно таки или WinSock или какие-то другие компоненты использовать.
Все Ваши рассуждения об синхроне/асинхроне - на мой взгляд не имеют под собой никакой основы. И опасения, извините, высосаны из пальца. Если у Вас есть ссылки откуда такая инфа - приведите. Я имею ввиду Асинхронные сокеты - это если у вас клиентов немного, тогда можно работать и через них, все клиенты обслуживает один и тот же поток. Если Вы имели ввиду Ваш компонент, то на нем действительно нормального сервера не написать - тут WinSock и статьи А.Григорьева Вам в помощь.
Асинхронные сокеты - это если у вас клиентов немного, тогда можно работать и через них, все клиенты обслуживает один и тот же поток.
Я вот думаю - если серверу моему немного трекеров надо будет обрабатывать, может и на асинхронных сокетах остановиться, там хоть есть события все эти ClientRead/ClientWrite, ClientConnect/ClientDisconnect...
Просто если программе придется держать связь с большим числом клиентов, такой сервер захлебнется от вала информации.
Да и там же может быть склейка пакетов при асинхронном режиме.
Чисто для пробы, я ж пока только с одним единственным трекером работаю, можно и асинхронный сервер написать. Посмотреть хоть, как оно в таком случае работать будет.
Никогда не "зарывался" столь глубоко, да и использовать блокирующие сокеты...нафиг нужно. Не сталкивался ни разу с такой необходимостью, да и у Вас она надуманная (мне так кажется).
Вот Вам код приема пакета с заголовком и, возможно, с "телом" разной длины. Написан был потомок, в котором перекрыт OnClientRead вот таким образом.
procedure TfmViewer.ssMainClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
ReadSocket(Handle,MessRecivPacket,Socket);
end;
procedure ReadSocket(Handle: HWnd; Mess: Cardinal; Socket : TCustomWinSocket);
var
CurrAddr: Pointer;
Count: Integer;
// Msg: TMessage;
begin
if Socket.Data = nil
then begin
// т.е. ничего ранее принято не было, или предыдущий пакет был принят полностью
GetMem(Pointer((@Socket.Data)^),sizeof(TPacket));
ZeroMemory(Socket.Data,sizeof(TPacket));
TPacket(Socket.Data^).Socket := Socket;
TPacket(Socket.Data^).WaitByte := sizeof(TDataPacket);//это размер заголовка
CurrAddr:=@TPacket(Socket.Data^).Packet;
end
else // т.е. идет "доприем" пакета
with TPacket(Socket.Data^) do
if Header //проверка на принятие полностью заголовка
then CurrAddr := Pointer(Integer(@Packet)+sizeof(TDataPacket)+Packet.DataSize-WaitByte)
else CurrAddr := Pointer(Integer(@Packet)+sizeof(TDataPacket)-WaitByte);
while TPacket(Socket.Data^).WaitByte > 0 do begin
Count := Socket.ReceiveBuf(CurrAddr^, TPacket(Socket.Data^).WaitByte); // попытка чтения "ожидаемого" кол-ва байт
if Count > 0
then begin // инкремент/декремент нужных полей на кол-во принятого
dec(TPacket(Socket.Data^).WaitByte,Count);
inc(Cardinal(CurrAddr),Count);
end
else Break;
end;
if (TPacket(Socket.Data^).WaitByte = 0) then begin
// т.е. мы прочитали все, что ожидали
if not TPacket(Socket.Data^).Header
then begin
// заголовок пакета прочитан
if (TPacket(Socket.Data^).Packet.Marker = StartMarker) and
(TPacket(Socket.Data^).Packet.PacketType in [ptConnect..ptWait])
then begin
//заголовок пакета корректен
TPacket(Socket.Data^).Header := True;
if TPacket(Socket.Data^).Packet.DataSize = 0
then begin
//больше читать в пакете нечего
PostMessage(Handle,Mess,Integer(Socket.Data),0);
Socket.Data := nil;
end
else begin
//есть пристыкованные данные
TPacket(Socket.Data^).WaitByte := TPacket(Socket.Data^).Packet.DataSize;
ReallocMem(Pointer((@Socket.Data)^),sizeof(TPacket)+TPacket(Socket.Data^).WaitByte);
end;
end
else begin
// тут всякая фигня, которая никогда не работает, но в коде есть
// т.е. заголовок некорректен и идет попытка найти в принятом "корректный" заголовок
// "скольжением" по буферу
end
end
else begin
PostMessage(Handle,Mess,Integer(Socket.Data),0);
Socket.Data := nil;
end;
end;
end;
В WireShark, когда ответ *<A<size> отсылается, то видно, что опять передается сообщение *>A<size><x[0]-x[size-1]>, где <x[0]-x[size-1]> - массив записей телеметрии, а <size> - их количество.
Только не сразу это *>A появляется после ответа, а там может несколько раз пройти пинг-сообщение о текущем состоянии трекера, а потом уже опять *>A.
Так что вроде как все согласно протоколу.
Но в том то и дело, впечатление такое, что трекеру будто не доходит, что я ему таки ответил.
Ведь запись телеметрии все время одна и та же, а должны после ответа пойти новые.
Одни тольки пинги в виде текущего состояния каждые 30 сек и видно нормально.
Да, но у меня же блокирующий режим. А там используются методы TWinSocketStream - Read(Buf, Count) - чтение и Write(Buf, Count) - запись в сокет.
Порывшись в сети, я увидел, что как-то можно использовать OnClientRead/OnClientWrite и в блокирующем режиме.
Но не вижу что-то понятного примера нигде как это использовать.
Видел только на форуме RSDN слова, что в таком случае не надо перекрывать метод Execute у TServerClientThread, а работать именно в OnClientRead/Write.
Вот интересно бы посмотреть бы подробнее код, как такое делается.
Справка, говорит, мол, получите ссылку на поток конкретного клиента через GetClientThread и дальше работайте с этим.
Даже разбираться в Вашем коде не хочется, потому что...
1. Давно не работал с TServerSocket-ом, но... У него же есть эвент OnClientRead. Откуда тогда вот этот ReadHeader в GetGPSData с
bytes_read := FCliSock.Read(hdr_Byte, 1);
mhead.Write(hdr_byte, bytes_read);
total_read := total_read + bytes_read;
????
Вы что поллингом (тупым чтением) пытаетесь что-то получать???? Когда захотел - тогда и начал пытаться доставать стек драйверов "отдай змей мне по одному байту"? Такой способ положен в основу "задр..ния серверов", эдакая разновидность DOS-атаки. Не так много способных обслуживать пару/тройку десятков клиентов, запросивших мегабайты, но читающих по одному байту, да и еще с задержками...остальные (сервера) просто валятся.
2.Сказано в протоколе, что на сообщение *>A нужно ответить количеством записей в массиве - *<A<количество записей>. Ну так и отвечаю. Однако запись все равно одна и та же. Ну не может такого быть, мне говорят. - а чем это подтверждается? Что показывает сниффер обмена (например wireshark)?
except
on E: ESocketConnectionError do
begin
ServerLogAddSync('Заголовок не принят - разрываю соединение');
ShowMessageFmt('Исключение %s в классе %s', [E.Message, E.ClassName]);
if (total_read = 16) and (Header.Preamble[0] = ADevice.Preamble[1]) and (Header.Preamble[1] = ADevice.Preamble[2])
and (Header.Preamble[2] = ADevice.Preamble[3]) and (Header.Preamble[3] = ADevice.Preamble[4]) then
begin
{$IFDEF DEBUG}
ServerLogAddSync('ВСЕ 16 БАЙТ ЗАГОЛОВКА ПРИНЯТЫ НОРМАЛЬНО.');
{$ENDIF}
Result := true;
end
else
begin
ServerLogAddSync('Заголовок пакета не удалось принять');
Result := false;
end;
end;
function TMICRC(Data: TMI_Type_F5_2): byte;
var i: byte;
b: ^byte;
s: byte;
begin
b := @Data;
s := 0;
for i := 0 to SizeOf(TMI_Type_F5_2) do
begin
s := s xor b^;
{ sum := sum xor ord(cmd[i]); }
Inc(b);
end;
Result := s;
end;
begin
ServerLogAddSync('Подготовка к приему пакета телеметрии...');
{ Сюда попадаем - если пакет пустой, т.е. заголовок без данных }
{$IFDEF DEBUG}
AssignFile(TMI_Hex, 'GPS_INFO.HEX');
if FileExists('GPS_INFO.HEX') then Append(TMI_Hex) else Rewrite(TMI_Hex);
write(TMI_Hex, '['+TimeToStr(Now)+']'+#32); { регистрируем время заголовка }
{ запись заголовка пакета в HEX-дамп }
HdrByte := @Hdr;
for j := 0 to SizeOf(TPacketHeader)-1 do
begin
write(TMI_Hex, IntToHex(HdrByte^, 2)+#32);
Inc(HdrByte);
end;
// сколько GPS-записей принято?
write(TMI_Hex, IntToHex(RecsCount, 2)+#32);
// филлер для разделения блоков данных -
for j := 0 to 15 do write(TMI_Hex, 'FF'+#32);
Writeln(TMI_Hex);
Writeln(TMI_Hex);
{$ENDIF}
{ Если заголовок пустой - отвечаем, что не приняли ничего }
ServerLogAddSync('ПУСТОЙ ПАКЕТ - отвечаем об этом');
ShowRecvPacketSync('#EMPTY');
CloseFile(TMI_Hex);
if (AsText = True) then
begin
AssignFile(TMI_Text, 'GPS_INFO.TXT');
if FileExists('GPS_INFO.TXT') then Append(TMI_Text) else Rewrite(TMI_Text);
LogHeaderAsText(TMI_Text, Hdr);
CloseFile(TMI_Text);
end;
end
else
begin
(* А эта ветка обрабатывается, если Hdr.DataSize>0, значит данные в пакете есть.
Но почему-то нормальной выгрузки черного ящика добиться не удается *)
{ Эти файлы для журналирования приема данных в HEX и в читаемом виде }
AssignFile(TMI_Hex, 'GPS_INFO.HEX');
if FileExists('GPS_INFO.HEX') then Append(TMI_Hex) else Rewrite(TMI_Hex);
if AsText = true then
begin
AssignFile(TMI_Text, 'GPS_INFO.TXT');
if FileExists('GPS_INFO.TXT') then Append(TMI_Text) else Rewrite(TMI_Text);
end;
write(TMI_Hex, '['+TimeToStr(Now)+']'+#32); { регистрируем время заголовка }
HdrByte := @Hdr;
{ скидываем заголовок в hex-файл }
for j := 0 to SizeOf(TPacketHeader) do
begin
write(TMI_Hex, IntToHex(HdrByte^, 2)+#32);
Inc(HdrByte);
end;
for j := 0 to 15 do write(tmi_hex, 'FF'+#32);
writeln(TMI_Hex);
writeln(TMI_Hex);
{ в другой файл - заголовок в читаемом человеком виде }
if AsText then LogHeaderAsText(TMI_Text, Hdr);
RecsCount := 0;
FillChar(RecvBuf, SizeOf(recvbuf), 0);
{ Если заголовок не был пустым - принимаем блок данных }
mfile := TMemoryStream.Create;
tr := 0;
while (tr < hdr.DataSize) do
begin
br := FCliSock.Read(RecvBuf, 1);
mfile.Write(recvbuf, br);
tr := tr + br;
end;
mfile.Seek(0, soFromBeginning);
SetLength(TMI_Bytes, hdr.DataSize);
mFile.Read(TMI_Bytes[0], hdr.DataSize); { считываем весь пакет в массив }
write(TMI_Hex, '['+TimeToStr(Now)+']'+#32); { записываем время приема пакета }
{ в этом if разбираемся, что за пакет пришел и
шлем соответствующие ответы }
if head = '*>A' then
begin
ShowRecvPacketSync(head);
mfile.Seek(3, soFromBeginning);
mFile.Read(RecsCount, 1);
{ Ответ на пакет *<A<количество записей> }
DebGPSDataReceived(ADevice, RecsCount);
if RecsCount = 2 then
begin
{ Тут если первый же пакет склеен с текущей телеметрией,
то я их разделяю, чтоб в журнале посмотреть }
mFile.Seek(4, soFromBeginning);
mfile.read(BlackRec, SizeOf(TMI_Type_F5_2));
mFile.Seek(5, soFromBeginning);
mFile.Read(Rec_No, 4);
mFile.Seek(11, soFromBeginning);
mfile.Read(ANextEvent, SizeOf(TEventTime));
mfile.Seek(90, soFromBeginning);
mFile.Read(BlackRec2, SizeOf(TMI_Type_F5_2));
mFile.Seek(97, soFromBeginning);
mFile.Read(DummyTime2, SizeOf(TEventTime));
end
else
begin
mFile.Seek(4, soFromBeginning);
mFile.Read(BlackRec, SizeOf(TMI_Type_F5_2));
mfile.Seek(5, soFromBeginning);
mFile.Read(Rec_No, 4);
mFile.Seek(11, soFromBeginning);
mfile.Read(ANextEvent, SizeOf(TEventTime));
end;
TelRec := NRec;
for j := 0 to High(TMI_Bytes) do write(TMI_Hex, inttohex(tmi_bytes[j], 2)+#32);
if AsText = true then
begin
if RecsCount = 2 then
begin
LogPacketAsText(TMI_Text, head, RecsCount, DummyTime, 0, BlackRec);
LogPacketAsText(TMI_Text, head, RecsCount, DummyTime2, 0, BlackRec2);
end
else begin
LogPacketAsText(TMI_Text, head, RecsCount, DummyTime, 0, BlackRec);
end;
end;
end
else if head = '*>T' then
begin
ShowRecvPacketSync(head);
mFile.Seek(4, soFromBeginning);
// CurIndex - номер записи, почему-то он всегда 0 у сообщения *>T
mFile.Read(CurIndex, 4);
mFile.Seek(3, soFromBeginning);
mfile.Read(BlackRec, SizeOf(TMI_Type_F5_2));
ServerLogAddSync(Format('Посылка ответа на текущее сост. %d', [CurIndex]));
SendCurrentStatusAnswer(ADevice, CurIndex);
for j := 0 to High(TMI_Bytes) do write(TMI_Hex, inttohex(tmi_bytes[j], 2)+#32);
if (AsText = true) then LogPacketAsText(TMI_Text, head, 1, DummyTime, 0, BlackRec);
end
else if head = '*#I' then
begin
ShowRecvPacketSync(head);
if (head <> '*>T') and (head <> '*>A') then Sum_No := Sum_No + 1;
ServerLogAddSync('Принят пакет *#I');
SetLength(TMI_Bytes, hdr.DataSize);
mFile.Seek(3, soFromBeginning);
mfile.Read(BlackRec, SizeOf(TMI_Type_F5_2));
BlackRecPtr := @BlackRec;
ServerLogAddSync('Индекс принятой записи '+inttostr(FTelRec));
if (head <> '*>A') and (head <> '*>T') then FNewRec := FNewRec + 1;
if AsText = false then
begin
write(TMI_Hex, '('+inttostr(FNewRec)+')'+#32);
for j := 0 to (SizeOf(TMI_Type_F5_2)) do
begin
write(TMI_Hex, inttohex(BlackRecPtr^, 2)+#32);
Inc(BlackRecPtr);
end;
end
else LogPacketAsText(TMI_Hex, head, 1, DummyTime, 0, BlackRec);
end
else if head = '*#R' then
begin
{ Попробуем таки принимать тут пакеты *#R - ближайшие записи
ПОСЛЕ даты, указанной в параметре запроса }
ShowRecvPacketSync(head);
mfile.Seek(3, soFromBeginning);
mfile.Read(NumRTime, SizeOf(TEventTime));
mfile.Seek(9, soFromBeginning);
mfile.Read(APage, 4);
mfile.Seek(13, soFromBeginning);
mFile.Read(BlackRec, SizeOf(TMI_Type_F5_2));
mFile.Seek(20, soFromBeginning);
mfile.Read(ANextEvent, SizeOf(TEventTime));
if (AsText = true) then LogPacketAsText(TMI_Hex, head, 1, NumRTime, APage, BlackRec);
end
else if head = '*#A' then
begin
ShowRecvPacketSync(head);
ServerLogAddSync('Принят ответ на запрос текущего состояния - *#A');
mFile.Seek(3, soFromBeginning);
mFile.Read(BlackRec, SizeOf(TMI_Type_F5_2));
mfile.Seek(10, soFromBeginning);
mFile.Read(NumRTime, SizeOf(TEventTime));
if AsText then LogPacketAsText(TMI_Text, head, 1, NumRTime, 0, BlackRec);
end;
for j := 0 to 15 do write(TMI_Hex, 'FF'+#32);
Writeln(TMI_Hex);
Writeln(TMI_Hex);
Finalize(TMI_Bytes);
CloseFile(TMI_Hex);
if (AsText = true) then CloseFile(TMI_Text);
mfile.Free; { уничтожаем временный буфер }
end;
end
else
begin
ServerLogAddSync('Заголовок пакета телеметрии не удалось принять');
end;
end;
А ответ на телеметрическое сообщение *>A так делается:
procedure TDeviceClient.DebGPSDataReceived(ADevice: TDevice; recordCount: byte);
var Hdr: TPacketHeader;
Data: array [0..3] of byte;
b: ^Byte;
k: byte;
n: byte;
s: string;
begin
{ Отсылаем ответ, что телеметрические записи получены }
{ заголовок }
for n := 1 to 4 do Hdr.Preamble[n-1] := ADevice.Preamble[n];
13-02-2012 23:54 | Комментарий к предыдущим ответам
Получается, зря только сюда постил - откуда такие выводы? Человек, когда родился, умеет только две вещи...остальному учится.
Запости, получил "пинка" (замечу в нужном направлении) и разобрался. А для каких целей тогда Королевство существует? Как только оно скатится до конечных решений и кодов - удалю у себя из ссылок. ;-)
Да, я кажется понял. Оказалось, провтыкал насчет одного места в протоколе - там же кажый пакет данных, будь то команда, запрос или информация - сопровождаются небольшим заголовком.
Уже сделал чтоб сформировало и отослало заголовок пакета для команды перед самой командой.
Осталось только добиться получения ответов на эти команды, и тогда будет уже работать.
Так вот тебе с NTCB работать и нужно. Именно он обеспечивает интерфейс по TCP/IP а NMEA - для локального использования через UART модуля.
Какие функции заявляет NTCB? Что именно там непонятно?
Темболее, по вашим словам авторизация происходит - значит часть протокола Вы уже выполнили... остается дело за малым, выполнить остальную часть!
Блин, почитал описалово СИГНАЛ S-2117...посмеялся...
Надо же так заявлять о точности!!! Пусть поставят модуль на открытой местности и по-честному нарисуют на карте отсчеты от навигационного модуля в течение 2-3 часов. Если у них получится "розочка" с диаметром меньше 15 м - скажу, что они молодцы. Почти уверен, что меньше 50 м не получится!!!
Нет, Вы подождите... Если у Вас есть некая железяка СИГНАЛ S-2117, то для того, чтобы что-нибудь сваять на ее базе НАДО иметь доку по протоколу общения с ней. Наверняка к ней имеется ПО, которое конфигурит ее, в плане:
1. Параметры соединения по GPRS (EDGE, и прочая).
2. Параметры и способы передачи сообщений, а именно м.б.
2.1. URL почтовика и параметры аккаунта и почтового ящика.
2.2. Параметры модема для передачи СМС-ок.
2.3. Хрен его знает, какой еще способ придумали разработчики СИГНАЛ S-2117.
3. Кол-во и тип "тревожных" датчиков на шлейфах.
4. Ну и прочая ерунда.
Отсюда вывод:
1. Не умеет передавать сообщения в виде "письма на мыло" - значит трындец, Ваше начальство обломалось с экономией на СМС-ках.
2. Навряд ли по ТСР есть возможность программировать п.2.
3. GPS-модули можно посредством NMEA программировать на набор и периодичность получения параметров (координаты, время, кол-во спутников и пр.), но... навряд-ли это возможно по ТСР соединению. Почему? Потому что о том, что у СИГНАЛ S-2117 есть Навстар/Глонасс-модуль Вы можете только догадываться. Говоря на языке ООП, он - в секции protected.
4. Опять же на ООП - в public у Вас только модуль, обеспечивающий ТСР-соединение. Есть в этой секции процедура трансляции команд в Навстар/Глонасс-модуль - читайте описание NMEA и пробуйте, но...это вряд ли. Очень сильно ВРЯД ЛИ!!!
Не совсем понятно, что еще за "железка" и при чем она тут.
Почитав описание GPS-приемника, я вижу, что там, действительно, два UART интерфейса - один для данных NMEA, другой для BINR - собственного протокола приемника.
Только он же используется для настройки приемника. По BINR состояние датчиков трекера и координаты не получишь.
Вообще-то, как правило GPS-чип оснащен UART-интерфейсом и после того как включился инашел спутники с установленной периодичностью(примерно 1..10 раз в секунду) выдает текущие координаты в интерфейс. В вашем случае, между GPS и TCP/IP стеком находится железка-клиент, которая и управляет GPS-чипом. Вам нужно знать протокол работы именно с ЭТОЙ железкой и забыть про GPS-чип, вам он через сеть НЕДОСТУПЕН и "общатся" можно только с этой промежуточной железкой.
Ну сам то IP трекера еще получаю, это да. Его же в OnAccept и получаем.
А вот как по GPRS трекером управлять, чтобы нужные данные получать - не очень понятно.
Вроде управление СМС-командами там, но у нас требуется, чтобы желательно без них, так как быстро ж деньги на счету так кончатся, если СМС-ками принимать каждые, скажем, 30 сек координаты.
Вот тут http://cybermonitor.ru работает же как-то через Интернет без всяких там СМС. Вот что-то подобное и нужно.
Конечно же, трекер - это клиент с точки зрения TCP/IP соединения.
После установки соединения он сам передает строку идентификации, так что авторизацию сделать получилось.
А вот дальше нужно каким-то образом передавать ему команды получения текущего состояния устройства и текущих координат, и т.д.
Вот насчет того, как программно им управлять, как раз информации нет. Есть только описание протоколов NTCB и NMEA.
Вообще, я читал, конечно, что например, на мобильные телефоны, можно смс-ки слать как электронную почту, используя как адрес телефона "номер@сайт оператора".
01-02-2012 20:24 | Вопрос к автору: запрос дополнительной информации
GPS-трекерами -да Вы хоть чертом лысым назовите эти устройства. Вы для себя уясните, что собой они представляют сервера или клиенты с точки зрения установки связи по ТСР. По идее подобные устройства являются клиентами. Получив по жэпээрэсу (или еще как) соединение, они коннектятся по (заложенному в их "мозгах") урлу или непосредственно IP. А под этим IP может быть и почтовик и приемник SMS-ок...как разработчик изхитрится.
Озвучьте эту инфу - будет конкретный ответ. А пока есть сомнения по поводу успеха предприятия из-за Описание протокола есть, но по нему не ясно, как передавать команды и получать ответы ... ;-)
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.