📄 devreader.pas
字号:
unit DevReader;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, JvHidControllerClass, ExtCtrls, ComCtrls, Mask, inifiles;
type
TPlaybackResult = (pbIgnore, pbSuccess, pbFail);
TUPSSTATE = packed record
InputPower: string; //输入电压
OutputPower: string; //输出电压
PowerLoad: string; //负载
Tmprt: string; //温度
end;
TReport = packed record
ReportID: Byte;
Bytes: array[0..63] of Byte;
end;
TMainForm = class(TForm)
HistoryListBox: TListBox;
HidCtl: TJvHidDeviceController;
OpenDateTimePicker: TDateTimePicker;
CloseDateTimePicker: TDateTimePicker;
Label3: TLabel;
Label4: TLabel;
Timer1: TTimer;
Button1: TButton;
Button2: TButton;
DevListBox: TListBox;
Label1: TLabel;
Button3: TButton;
Timer2: TTimer;
procedure FormActivate(Sender: TObject);
procedure HidCtlDeviceChange(Sender: TObject);
function HidCtlEnumerate(HidDev: TJvHidDevice;
const Idx: Integer): Boolean;
procedure HidCtlDeviceDataError(HidDev: TJvHidDevice; Error: Cardinal);
procedure HidCtlRemoval(HidDev: TJvHidDevice);
procedure DevListBoxClick(Sender: TObject);
procedure InfoBtnClick(Sender: TObject);
procedure ClearBtnClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Timer2Timer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
public
Activated: Boolean;
CurrentDevice: TJvHidDevice;
Readdata, tmpReadData: string;
UPSSTATE: TUPSSTATE;
function DeviceName(HidDev: TJvHidDevice): string;
procedure ShowRead(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word);
procedure AddToHistory(Str: string);
function SendCommand(const Senddata: array of Byte): boolean;
function UpsvListBox: boolean;
function WinExitInNT(iFlags: integer): boolean;
function SetPrivilege(sPrivilegeName: string; bEnabled: boolean): boolean;
procedure Delay(waittime: integer);
procedure InsertLogfile(log_str: string); //记录关机日志
procedure MinMin(var Msg: TWMSYSCOMMAND); message WM_SYSCOMMAND;
end;
var
MainForm: TMainForm;
implementation
uses
Math,
Info;
{$R *.dfm}
procedure TMainForm.FormActivate(Sender: TObject);
var
I, J: Integer;
Dev: TJvHidDevice;
begin
if not Activated then
begin
Activated := True;
DevListBoxClick(Self);
end;
end;
procedure TMainForm.HidCtlDeviceChange(Sender: TObject);
var
Dev: TJvHidDevice;
I, N: Integer;
begin
for I := 0 to DevListBox.Items.Count - 1 do
begin
Dev := TJvHidDevice(DevListBox.Items.Objects[I]);
Dev.Free;
end;
DevListBox.Items.Clear;
while HidCtl.CheckOut(Dev) do
begin
N := DevListBox.Items.Add(DeviceName(Dev));
Dev.NumInputBuffers := 128;
Dev.NumOverlappedBuffers := 128;
DevListBox.Items.Objects[N] := Dev;
end;
end;
function TMainForm.DeviceName(HidDev: TJvHidDevice): string;
begin
if HidDev.ProductName <> '' then
Result := HidDev.ProductName
else
Result := Format('Device VID=%.4x PID=%.4x',
[HidDev.Attributes.VendorID, HidDev.Attributes.ProductID]);
if HidDev.SerialNumber <> '' then
Result := Result + Format(' (Serial=%s)', [HidDev.SerialNumber]);
end;
function TMainForm.HidCtlEnumerate(HidDev: TJvHidDevice; const Idx: Integer): Boolean;
var
N: Integer;
Dev: TJvHidDevice;
begin
N := DevListBox.Items.Add(DeviceName(HidDev));
HidCtl.CheckOutByIndex(Dev, Idx);
Dev.NumInputBuffers := 128;
Dev.NumOverlappedBuffers := 128;
DevListBox.Items.Objects[N] := Dev;
Result := True;
end;
procedure TMainForm.DevListBoxClick(Sender: TObject);
var
I: Integer;
Dev: TJvHidDevice;
begin
// stop reader thread
if Assigned(CurrentDevice) then
CurrentDevice.OnData := nil;
CurrentDevice := nil;
if (DevListBox.Items.Count > 0) and (DevListBox.ItemIndex >= 0) then begin
Dev := TJvHidDevice(DevListBox.Items.Objects[DevListBox.ItemIndex]);
Dev.OnData := ShowRead;
CurrentDevice := Dev;
AddToHistory('设备名称:' + DeviceName(CurrentDevice));
end;
end;
procedure TMainForm.AddToHistory(Str: string);
var
N: Integer;
begin
HistoryListBox.Canvas.Font := HistoryListBox.Font;
N := HistoryListBox.Canvas.TextWidth(Str) + 16;
if HistoryListBox.ScrollWidth < N then
HistoryListBox.ScrollWidth := N;
HistoryListBox.ItemIndex := HistoryListBox.Items.Add(Str);
HistoryListBox.ClearSelection;
end;
procedure TMainForm.ShowRead(HidDev: TJvHidDevice; ReportID: Byte;
const Data: Pointer; Size: Word);
var
I, j: Integer;
Str, tmp: string;
Hexstr: Byte;
begin
str := '';
for I := 0 to Size - 1 do begin
Str := Format('%.2x', [Cardinal(PChar(Data)[I])]);
tmpReadData := tmpReadData + Str + ' ';
ReadData := ReadData + Str;
if Str = '0D' then begin
AddToHistory('读数据:' + tmpReadData);
for j := 1 to (Length(ReadData) div 2) do begin
Hexstr := StrToInt('$' + Copy(ReadData, j * 2 - 1, 2));
if Hexstr <> $28 then tmp := tmp + Chr(Hexstr);
end;
AddToHistory(tmp);
UPSSTATE.InputPower := Copy(tmp, 1, pos(' ', tmp) - 1);
Delete(tmp, 1, pos(' ', tmp));
Delete(tmp, 1, pos(' ', tmp));
UPSSTATE.OutputPower := Copy(tmp, 1, pos(' ', tmp) - 1);
Delete(tmp, 1, pos(' ', tmp));
UPSSTATE.PowerLoad := Copy(tmp, 1, pos(' ', tmp) - 1);
Delete(tmp, 1, pos(' ', tmp));
Delete(tmp, 1, pos(' ', tmp));
Delete(tmp, 1, pos(' ', tmp));
UPSSTATE.Tmprt := Copy(tmp, 1, pos(' ', tmp) - 1);
AddToHistory('输入电压:' + UPSSTATE.InputPower);
AddToHistory('输出电压:' + UPSSTATE.OutputPower);
AddToHistory(' 负载:' + format('%d', [StrToint(UPSSTATE.PowerLoad)]) + '%');
AddToHistory(' 温度:' + UPSSTATE.Tmprt);
end;
end;
end;
procedure TMainForm.HidCtlDeviceDataError(HidDev: TJvHidDevice; Error: Cardinal);
begin
AddToHistory(Format('READ ERROR: %s (%x)', [SysErrorMessage(Error), Error]));
end;
procedure TMainForm.HidCtlRemoval(HidDev: TJvHidDevice);
begin
AddToHistory('Removal of ' + DeviceName(HidDev));
end;
procedure TMainForm.InfoBtnClick(Sender: TObject);
begin
if (DevListBox.Items.Count > 0) and (DevListBox.ItemIndex >= 0) then
with TInfoForm.Create(Self) do
begin
Dev := TJvHidDevice(DevListBox.Items.Objects[DevListBox.ItemIndex]);
ShowModal;
Free;
end;
end;
procedure TMainForm.ClearBtnClick(Sender: TObject);
begin
HistoryListBox.Items.Clear;
HistoryListBox.ScrollWidth := 0;
end;
function TMainForm.SendCommand(const Senddata: array of Byte): boolean;
var
I: Integer;
Buf: array[0..64] of Byte;
Written: Cardinal;
ToWrite: Cardinal;
Str: string;
Err: DWORD;
begin
if Assigned(CurrentDevice) then
begin
for i := 0 to 64 do Buf[i] := $00;
ToWrite := CurrentDevice.Caps.OutputReportByteLength;
for i := 0 to ToWrite - 1 do
Buf[I + 1] := Senddata[i];
if not CurrentDevice.WriteFile(Buf, ToWrite, Written) then
begin
Err := GetLastError;
AddToHistory(Format('WRITE ERROR: %s (%x)', [SysErrorMessage(Err), Err]));
end
else
begin
Str := Format('写数据: %.2x ', [Buf[0]]);
for I := 1 to Written - 1 do
Str := Str + Format('%.2x ', [Buf[I]]);
AddToHistory(formatdatetime('yyyy-mm-dd hh:mm:ss', now) + ' State>>' + #13 + Str);
end;
end;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
winexec('.\osk.exe', 0);
end;
function TMainForm.UpsvListBox: boolean;
var
I: Integer;
Dev: TJvHidDevice;
UpsName: string;
begin
try
Result := false;
if Assigned(CurrentDevice) then CurrentDevice.OnData := nil;
CurrentDevice := nil;
if (DevListBox.Items.Count > 0) then begin
for i := 0 to DevListBox.Items.Count - 1 do begin
UpsName := trim(DevListBox.Items.Strings[i]);
if pos('USB to Serial', UpsName) > 0 then begin
Dev := TJvHidDevice(DevListBox.Items.Objects[i]);
Dev.OnData := ShowRead;
CurrentDevice := Dev;
AddToHistory('UPS设备名称:' + DeviceName(CurrentDevice));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -