Форум сайта python.su
Имеется старый проект на Delphi, который, используя функции из DLL, читает по сети показания контроллера.
Подключение DLL в Delphi (RDTCP.PAS):
unit RDTCP;
interface
type
PDat=^TDat;
TDat=packed record
PVal:single; // Значение, для дискретных 1.0 - это true, 0.0 - это false
IsOK:byte;
end;
function TCP_Init(ip:PChar; port:word; tconnect:cardinal; tread:cardinal):pointer;stdcall;
procedure TCP_Close(H:pointer);stdcall;
function TCP_Connect(H:pointer):integer;stdcall; // 0-OK -1-error
procedure TCP_Disconnect(H:pointer);stdcall; // 0-OK -1-error
function TCP_GetAKolPar(H:pointer):integer;stdcall;
function TCP_RdAllAn(H:pointer):integer;stdcall;
function TCP_GetAnPar(H:pointer;s:PChar):TDat;stdcall;
function TCP_RdAnPar(H:pointer; s:PChar; var D:TDat):integer;stdcall; // 0-OK -1-error
function TCP_GetDKolPar(H:pointer):integer;stdcall;
function TCP_RdAllDi(H:pointer):integer;stdcall;
function TCP_GetDiPar(H:pointer;s:PChar):TDat;stdcall;
function TCP_RdDiPar(H:pointer; s:PChar; var D:TDat):integer;stdcall; // 0-OK -1-error
implementation
function TCP_Init; external 'RDTCP.DLL';
procedure TCP_Close; external 'RDTCP.DLL';
function TCP_Connect; external 'RDTCP.DLL';
procedure TCP_Disconnect; external 'RDTCP.DLL';
function TCP_GetAKolPar; external 'RDTCP.DLL';
function TCP_RdAllAn; external 'RDTCP.DLL';
function TCP_GetAnPar; external 'RDTCP.DLL';
function TCP_RdAnPar; external 'RDTCP.DLL';
function TCP_GetDKolPar; external 'RDTCP.DLL';
function TCP_RdAllDi; external 'RDTCP.DLL';
function TCP_GetDiPar; external 'RDTCP.DLL';
function TCP_RdDiPar; external 'RDTCP.DLL';
end.
procedure TForm1.FormShow(Sender: TObject);
begin
// TCP_Init вызывается при запуске проги
Hnd_Bl:=nil;
// В этом примере для хоста 172.28.72.2 используется порт 9123.
// А вообще по умолчанию везде порт 9000
Hnd_Bl:=TCP_Init('192.168.7.5',9000,5000,5000); // IP, port, timeout_connect, timeout_read
if Hnd_Bl=nil then begin
MessageDlg('Ошибка TCP_Init',mtError,[mbOK],0);
Close;
end;
ReadAndShow;
CNT:=0;
end;
//---
procedure TForm1.ReadAndShow;
const cOK=$0080FFFF;
cER=clGray;
var D:TDat;
begin
// TCP_RdAllAn читает значения всех параметров во внутренний буфер
// Если TCP_RdAllAn возвр. 0 - ОК, если <0 - error
if TCP_RdAllAn(Hnd_Bl)=0 then begin
StBar1.SimpleText:=FormatDateTime('dd-mm-yyyy hh:nn:ss',Now)+' - чтение данных - ОК';
end else StBar1.SimpleText:=FormatDateTime('dd-mm-yyyy hh:nn:ss',Now)+' - чтение данных - ERROR !!!';
// А дальше вытаскиваем значения параметров по их идентификаторам
D:=TCP_GetAnPar(Hnd_Bl,'BLT_TG1_PSUM');
if D.IsOK=1 then stP1.Color:=cOK else stP1.Color:=cER;
stP1.Caption:=FloatToStrF(D.PVal,ffFixed,5,1)+' ';
import ctypes RDTCP = ctypes.WinDLL("RDTCP.dll") IP = ctypes.c_char_p('192.168.7.5'.encode('cp1251')) port = ctypes.c_ushort(9000) timeout_connect = ctypes.c_ulong(5000) timeout_read = ctypes.c_ulong(5000) Hnd_Bl = RDTCP.TCP_Init(IP, port, timeout_connect, timeout_read) print(RDTCP.TCP_RdAllAn(Hnd_Bl)) print(RDTCP.TCP_GetAKolPar(Hnd_Bl)) BLT_TG1_PSUM = ctypes.c_char_p('BLT_TG1_PSUM'.encode('cp1251')) print(RDTCP.TCP_GetAnPar(Hnd_Bl, BLT_TG1_PSUM))
def send(self): return buffer(self)[:] def receiveSome(self, bytes): fit = min(len(bytes), ctypes.sizeof(self)) ctypes.memmove(ctypes.addressof(self), bytes, fit)
class TDat(object): def __init__(self, PVal=ctypes.c_float(0.0), IsOK=ctypes.c_byte(0)): self.PVal = PVal self.IsOK = IsOK
Отредактировано thunderamur (Ноя. 13, 2016 09:42:07)
Прикреплённый файлы: rdtcp.py (991 байт)
Офлайн
Насколько я понял, тебе проще проснифить RAW комманды из длл, и отравлять запросы по TCP вручную из питона.
Ну и про ctypes, там вроде как нужен костыль при перегоне буфера из него в питон… я не помню, честно, но погугли. Я встречался с ним в теме про восстановление паролей из файерфокса, гдето на http://stackoverflow.com
Зы. и если ты лезешь в глубину… дельфофские библиотеки имеют другое “соглашение вызовов” по сравнению с сишными
Отредактировано Iskatel (Ноя. 13, 2016 14:36:08)
Офлайн
Спасибо за ответ. Да, мне лучше делать запросы из питона. Действительно, можно попробовать посмотреть как идет опрос.
Офлайн
попробуй wireshark.
запускаешь всю безобразию на дельфе, и держишь включенным wireshark.
Дальше не особо сложно, хоть и кажется. Узнаешь в логах хоть один пакет (по айпишнику) , и правой кнопкой жмешь Folow -> TCP stream. там будет все общение твоей длл с устройством
Отредактировано Iskatel (Ноя. 13, 2016 16:42:36)
Офлайн
И кстати, я не очень понимаю накуяэтотебенадо, но осмелюсь предположить, что горазто проще написать некоторую прослойку на дельфях, которая будет юзать ту библиотеку, а данные отдавать хочешь по сети, хочешь через файл, хочешь через тунель, иль по простятски через stdin / stdout.
Отредактировано Iskatel (Ноя. 13, 2016 17:05:06)
Офлайн
Дамп сделал, кадров немного, видна последовательность сообщений. Теперь вопрос как мне отправлять и получать сообщения в сети, а также в каком виде отправлять Data из Wireshark. Т.е. в Wireshark я могу взять данные из кадра, например “31:39:35:39:31:30:31:37:0a” как мне их отправить?
Iskatel
Да, можно поднять этот древний проект на Delphi, но лучшим решением будет работа только в Python.
Офлайн
Такс, данные можно отправлять в таком виде скорее всего
data = '31393539313031370a' b = bytes.fromhex(data)
import socket TCP_IP = '192.168.7.5' TCP_PORT = 9000 BUFFER_SIZE = 1024 MESSAGE = bytes.fromhex('31393539313031370a') s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((TCP_IP, TCP_PORT)) s.send(MESSAGE) data = s.recv(BUFFER_SIZE) s.close() print("received data:", data)
Офлайн
В общем опять затык на моменте чтения конкретных значений.
function TCP_GetAnPar(H:pointer;s:PChar):TDat;stdcall;
TDat=packed record
PVal:single; // Значение, для дискретных 1.0 - это true, 0.0 - это false
IsOK:byte;
end;
Офлайн
0000 07 f6 2a 43 01 00 00 00 00 42 4c 54 5f 47 54 50 ..*C.....BLT_GTP
0010 31 5f 50 53 55 4d 00 00 00 00 00 00 00 00 00 00 1_PSUM..........
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Офлайн
import binascii import struct h = '07f62a430100000000424c545f475450315f5053554d000000000000000000000000000000000000000000000000000000000000000000000000000000000000' b = binascii.unhexlify(h[:8]) print(struct.unpack('<{0}f'.format(1), b)[0]) b = binascii.unhexlify(h[8]+h[9]) print(struct.unpack('<{0}B'.format(1), b)[0])
170.961044312
1
Офлайн