

mikerabat
-
Content Count
45 -
Joined
-
Last visited
-
Days Won
1
Posts posted by mikerabat
-
-
Actually the fix I posted to Embarcadero was exactly that and a few things more. Basically they used
an outdated API and needed pairing.
The code there should fix that. Let me know if you can find it - if not let me know. Maybe I can send you the
fixed Windows BlueTooth LE stuff directly (I guess I may not post stuff here 😉 )
kind regards
MIke
-
Which Delphi version are you using?
I once fixed a few things in Bluetooth LE here https://quality.embarcadero.com/browse/RSP-20296 -let me know if that might help you.
kind regards
Mike
-
Strange enough on a second installation (aka our test site) the OnWork property works as expected... uploading around 1MByte per second
and not waiting at all at the end. It looks like there is some kind of proxy in between that first receives the full message - relays that to the
actual server - and waits until something comes back... I have though never heard of something like this and they couldn't clarify that either...
Is there actually some kind of hardware around that could reproduce such a behaviour?
-
Dear all!
Our Software supports new uploading large files (100MB + ) to a server. To get a nice feedback we wanted
to have some kind of progress telling the user how far we are already with the upload.
For the upload we use the TidHTTP component + an openssl io handler.
To get the progress working we used the OnWork event that is published by the component.
While we were using the component for testing in our internal network (which is quite fast) the
progress seemed ok but when we tested that on a slow network (around 2MBit) we saw that the first 99% were
very fast (20MB per second +) and then the last bytes "hang" until the full file was transmitted. Basically the
progress bar showed a progress of 99% for around 4minutes until the file was finally uploaded.
What am I missing here? How can I determine how much data is transmitted to the server?
The code involved is:
function CreateLibertyHTTP( method : TIdSSLVersion = sslvTLSv1_2; proxySet : ISuperObject = nil ) : TIdHTTP; var sslIOHandler : TIdSSLIOHandlerSocketOpenSSL; begin Result := TIdHTTP.Create(nil); sslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Result); sslIOHandler.SSLOptions.Method := method; Result.IOHandler := sslIOHandler; if (proxySet <> nil) and (proxySet.S['Server'] <> '') then begin Result.ProxyParams.ProxyServer := proxySet.S['Server']; if proxySet.I['Port'] <> 0 then Result.ProxyParams.ProxyPort := proxySet.I['Port']; if proxySet.s['Username'] <> '' then begin Result.ProxyParams.ProxyUsername := proxySet.s['Username']; Result.ProxyParams.ProxyPassword := proxySet.s['Pwd']; end; Result.ProxyParams.BasicAuthentication := proxySet.B['BasicAuthentication']; end; end;
httpReq := CreateLibertyHTTPReq( some params here ); DL.LLog(dlInfo, 'Liberty upload'); libertyParams.Clear; libertyParams.Add('SID=' + SessionId); libertyParams.Add('blockearly=1'); libertyParams.Add('csrfToken=' + csrfToken); // eg 'http://192.168.0.193:81/tom24x/uploadFile?SID=45784095&blockearly=1' s := httpReq.Post(LibServer+'tom24x/uploadFile', libertyParams, IndyTextEncoding_UTF8); if Pos('error', LowerCase(s)) > 0 then raise Exception.Create('Error initializing upload'); uplFileResp := SO(s); fUploadFileSize:=FileSizeByName(DawFileName); //s:='?SID='+SessionId+'&blockearly=1&overwrite=1'; // overwrite recording in case it's already uploaded Stream := TStringStream.Create(''); Params := TIdMultipartFormDataStream.Create; httpReq.OnWork:=LibertyUploadProgress; try Params.AddFile('pdf', DawFileName, 'application/octet-stream'); // New in 2.9.3: The Uploadfile issues a token which can be used as session id (one time thing) // so the param does no harm at all. s := LibServer+'rec/UploadRecording.exe?SID=' + uplFileResp.S['session'] + '&blockearly=1&overwrite=1'; // e.g. 'http://192.168.0.193:81/rec/UploadRecording.exe?SID=45784095&blockearly=1&overwrite=1' try httpReq.Post(s, Params, Stream); except on E: Exception do raise Exception.Create('Sending DAW file failed: ' + E.Message); end; DL.LLog(dlInfo, 'Liberty says: '+Stream.DataString);
procedure TfrmDBBrowser.LibertyUploadProgress(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64); function BytesToStr( numBytes : Int64 ) : string; begin if numBytes > 1000000 then begin Result := Format('%.2f MB', [numBytes/(1000*1000)]); end else if numBytes > 10000 then begin Result := Format('%d kB', [numBytes div 1000]); end else Result := intToStr( numBytes ) + ' B'; end; begin if fSxProgress.Cancelled then Abort else begin // note: the upload file size may be a bit higher than the actual file size due to header overhead fSxProgress.lblTopLabel.Caption := fLibertyUplLabel + ' ' + BytesToStr( Min(fUploadFileSize, AWorkCount ) ) + '/' + BytesToStr( fUploadFileSize ); fSxProgress.lblTopLabel.Update; fSxProgress.SetProgress(-1, MulDiv(AWorkCount, 100, fUploadFileSize)); end; end;
kind regards
Mike
-
17 hours ago, DelphiUdIT said:The WIN32 apis for BlueTooth are system based and are present in:
rtl/net/System.Bluetooth
rtl/net/System.Bluetooth.Components
That is only the one half of the story. This is the base - in the next abstraction layer Emba decided to go to the different platforms -
and for windows and Bluetooth LE the last file that actually implements stuff is System.Win.BluetoothWinRT.pas
17 hours ago, DelphiUdIT said:Some difference with use of BLE is that with Windows the devices must be paired almost one time to be used with BLE.
That is also not entierly true. The imlementation from Embarcadero lacks this ability yes - I managed though to extend the WinRT implementation such that this
is possible too.
See the attached file on:
https://quality.embarcadero.com/browse/RSP-21711hope that helps 😉
-
1
-
-
1 hour ago, DelphiUdIT said:I don't know the WinRT API and have never developed a UWP application.I would have created an external timer (a normal TTimer) and called the CancelDiscovery function without "touching" the BLE timer.In normal WIN32 api I do this and I have no problems whatsoever.And how do you do that in win32? I wasn't able to find any BT LE classes or functions besides the WinRT stuff that is covered in Delphi.
Please note that my code here patches the actual TBluetoothLE component that ships with Delphi 10.4.2!
And yes I use this code in conjunction with a standard VCL app 😉
-
I ran into the same problem and managed to fix that with an external timer that calls CancelDiscovery. It works but leaves a massive
memory/thread leak since every time a new discovery is started the timer variable gets overwritten and not freed leaving the pending thread and
it's resources....
The problem actually is:
the problem is within the Delphi implementation of the Thread that triggers the CancelDiscovery function.
In Windows there is a Thread (TWinRTBluetoothLEAdapter.TDiscoverThreadTimer in System.Win.BluetoothWinRT.pas) that
actually just waits for a specific amount of time and calls the given timer procedure. The problem here is that the
Timer procedure cleans up the thread (calls .Free) which waits for the end of the Thread -> deadlock.
To circumvent that problem I needed to adjust System.Win.BluetoothWinRT do the following:
Augment the class
TWinRTBluetoothLEAdapter
by
private
const WM_BTLE_CANCELDISCOVERY = $400 + 666; // WM_USER...
private
fHDL : HWND;
procedure BTLETimerHandler( var msg : TMessage );protected
procedure ThrDoCancelDiscovery;
..
implementation
procedure TWinRTBluetoothLEAdapter.BTLETimerHandler(var msg: TMessage);
begin
if msg.Msg = WM_BTLE_CANCELDISCOVERY then
DoCancelDiscovery;
end;procedure TWinRTBluetoothLEAdapter.ThrDoCancelDiscovery;
begin
// just post otherwise the thread hangs!
PostMessage( fHDL, WM_BTLE_CANCELDISCOVERY, 0, 0);
end;constructor TWinRTBluetoothLEAdapter.Create(const AManager: TBluetoothLEManager; const ARadioInfo: TBluetoothRadioInfo);
begin
inherited Create(AManager);
fHDL := AllocateHWnd(BTLETimerHandler);...
end;
destructor TWinRTBluetoothLEAdapter.Destroy;
begin
DeallocateHWnd(fHDL);...
end;
function TWinRTBluetoothLEAdapter.DoStartDiscovery(Timeout: Cardinal; const AFilterUUIDList: TBluetoothUUIDsList;
const ABluetoothLEScanFilterList: TBluetoothLEScanFilterList): Boolean;begin
...
// new code
if Assigned(fTimerThread) then
begin
fTimerThread.Cancel;
fTimerThread.Free;
end;// changed from DoCancelDiscovery to ThrDoCancelDiscovery
FTimerThread := TDiscoverThreadTimer.Create(Self, ThrDoCancelDiscovery, Timeout);
...
end;
I guess one could also use TThread.Queue instead of the "complicated" window allocation in the timer and that should do the trick too!
-
On 6/25/2021 at 9:06 PM, Remy Lebeau said:The main problem with TEncoding.GetBytes() is that its 'public' overloads all require the output to be a TBytes array, which you would then have to copy into your record afterwards, eg:
var patData : TPatData; SurName : String; Bytes: TBytes; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; Bytes := TEncoding.UTF8.GetBytes(SurName); Move(PBytes(Bytes)^, patData.SurName[0], Math.Min(SizeOf(patData.SurName), Length(Bytes))); ... end;
The one overload of GetBytes() that would actually let you output directly into your record without using TBytes is declared as 'strict protected', which means you can't use it without involving some hacks, eg:
type TEncodingHelper = class(TEncoding) public function GetBytes(const S: string; Bytes: PBytes; ByteCount: Integer): Integer; end; function TEncodingHelper.GetBytes(const S: string; Bytes: PBytes; ByteCount: Integer): Integer; begin Result := GetBytes(PChar(S), Length(S), Bytes, ByteCount); end; var patData : TPatData; SurName : String; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; TEncodingHelper(TEncoding.UTF8).GetBytes(S, PByte(@patData.SurName[0]), SizeOf(patData.SurName)); ... end;
Or:
type TEncodingHelper = class helper for TEncoding public function GetBytes(const S: string; Bytes: PByte; ByteCount: Integer): Integer; end; function TEncodingHelper.GetBytes(const S: string; Bytes: PByte; ByteCount: Integer): Integer; begin Result := Self.GetBytes(PChar(S), Length(S), Bytes, ByteCount); end; var patData : TPatData; SurName : String; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; TEncoding.UTF8.GetBytes(S, PByte(@patData.SurName[0]), SizeOf(patData.SurName)); ... end;
The alternative would be to use System.LocaleCharsFromUnicode() instead, eg:
var patData : TPatData; SurName : String; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; LocaleCharsFromUnicode(CP_UTF8, 0, PChar(SurName), Length(SurName), @patData.SurName[0], sizeof(patData.SurName), nil, nil); ... end;
Thank you very much much for the great insight!
-
23 minutes ago, David Heffernan said:TEncoding.UTF8.GetBytes
Sorry but can you elaborate that? I actually cannot see how I get there a string converted to a field in the record...
what am I missing here?
-
4 minutes ago, David Heffernan said:TEncoding.UTF8.GetBytes
You don't need to use AnsiString.
You mean I don't need AnsiCharacters to communicate with a device that only understands Single Byte characters?
So... how is that?
And tell me then how to use GetBytes to fill a structure like:
type
TPatData = packed record
SurName : Array[0..31] of AnsiChar;
FirstName : Array[0..31] of AnsiChar;
end;
var pat : TPatData;
formSurName : String;
begin
FillChar(pat, sizeof(pat), 0);
// code to be filled here....
end;
-
16 hours ago, Stefan Glienke said:Yes, ditch AnsiString.
haha...
I'd love to but I have file and communication structures that need good old ansi strings.
Or do you actually have a better idea than:
str8 := UTF8String(SurName);
System.AnsiStrings.StrLCopy(@patData.surname[0],PAnsiChar(str8), length(patData.surname));to bring a normal delphi string (SurName) to a structure (patData) that contains single byte characters?
-
Hi!
I'm currently migrating our projects from Delphi2010 to Delphi 10.4. One of my biggest
changes is actually using StrLCopy and other Ansistring functions that used to be in SysUtils.
They are now marked as deprecated and moved to System.AnsiStrings so ... I followed the compiler hint.
Now the base problem is that the compiler is confused which function to use so I always prefix the call
with
System.AnsiStrings.StrLCopy ...
which fixed that.
But that looks actually very "ugly" and I have the feeling that this is not the way to go idera ment to go.
Is there a "best" or anticipated way to handle this?
kind regards
Mike
-
You can check out:
https://github.com/mikerabat/mrmath
It provides a set of different random number generators:
* Standard delphi ( linear congruential )
* Mersenne Twister
* BCrypt (or actually os dependent)
* If the cpu supports it: the x86 RDRAND instruction
-
2
-
-
Hi there!
There is the C library libFido2 around in form of a dll. I took the liberty to put arround a Delphi library that supports
FIDO2 keys around that library including a little project that shows how one could do WebAuthn logins.
check out:
https://github.com/mikerabat/DelphiFido2
https://github.com/mikerabat/DelphiCBOR
for further reading.
kind regards
Mike
-
3
-
-
Hi!
You could use the regression functions from here:
https://github.com/mikerabat/mrmath
and the regression example from here:
http://www.mrsoft.org/home/downloads.html
-
1
-
-
Cool thanks for the info!
-
Thanks for the hint! I will definitely look into that 🙂
-
Hi Folks!
I hope anyone can give me some hints on this topic: Firebird Data encryption and encryption of the data sent.
Especially the "over the line" encryption of data is going to be mandatory for our next projects since there are
a few attack vectors we didn't really anticapte that this would ever be a problem: an attacker has access to an internal
network (e.g. a hospital) and reads the communication from between our program and the remote database.
So... data encryption ala SSL, TLS would be a great thing to have. So far the FAQ from firebird only suggest to
use an SSH tunnel or similar to connect to the database but ... is this feasable or even performant?
Has anyone any experience with such a problem or is there anything some Delphi components could do?
kind regards
Mike
-
Hey guys!
I wanted to share my matrix library with you
basically it contains tons of function for matrix manipulation (add, sub, mult, inverse)
and higher order functions (SVD, CCA, PLS and tons more)
The library is highly optimized (handoptimized assembler, AVX, SSE, FMA support) and can be multithreaded.
Check out the repository on
https://github.com/mikerabat/mrmath
and check some tiny examples on:
http://www.mrsoft.org/home/downloads.html
hope you have fun with that ;)
kind regards
Mike
-
1
-
5
-
Bluetooth LE only for paired Devices on Windows?
in Windows API
Posted
Hey Jo!
Actually there is already a 64bit compiler so.... I don't know what you are waiting for 😉
anyway.... the probelm is not the compiler but rather the api used aka WinRT and the fixes are
put in there in Delhi11 . So either update to this version or check the fixes.
I can remember that I also put them on stackoverflow: https://stackoverflow.com/questions/61890445/delphi-bluetooth-le-heart-rate-profile-access