デジタルマルチメータ OWON B35T (+) のデータを BLE で読んでみました (2017/05/24)

Bluetooth LE なので、Android / iOS から使えます。

■スクリーンショット(Android)


// for OWON BT35T
// Delphi 10.2 Tokyo
unit BDMUnit;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  System.Bluetooth, FMX.Controls.Presentation, FMX.StdCtrls,
  System.Bluetooth.Components, FMX.ScrollBox, FMX.Memo, FMX.Edit,
  Math, FMX.Objects;

type
  TForm2 = class(TForm)
    BluetoothLE1: TBluetoothLE;
    Button1: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Rectangle1: TRectangle;
    procedure Button1Click(Sender: TObject);
    procedure BluetoothLE1EndDiscoverDevices(const Sender: TObject;
      const ADeviceList: TBluetoothLEDeviceList);
    procedure BluetoothLE1EndDiscoverServices(const Sender: TObject;
      const AServiceList: TBluetoothGattServiceList);
    procedure BluetoothLE1CharacteristicRead(const Sender: TObject;
      const ACharacteristic: TBluetoothGattCharacteristic;
      AGattStatus: TBluetoothGattStatus);
  private
    { private 宣言 }
    fBDMDevice : TBluetoothLEDevice;
    fBDMService : TBluetoothGattService;
  public
    { public 宣言 }
  end;

var
  Form2: TForm2;

const
  BDMName : String = 'BDM';
  BDMService : TBluetoothUUID = '{0000FFF0-0000-1000-8000-00805F9B34FB}';
  BDMNotify  : TBluetoothUUID = '{0000FFF4-0000-1000-8000-00805F9B34FB}';

implementation

{$R *.fmx}

// 受信
procedure TForm2.BluetoothLE1CharacteristicRead(const Sender: TObject;
  const ACharacteristic: TBluetoothGattCharacteristic;
  AGattStatus: TBluetoothGattStatus);
var
  s : string;
  B : TBytes;
  i : integer;
  v : integer;
  dp : integer;
  f : double;
  u : string;
begin
  B := ACharacteristic.GetValue;
  s := '';
  // 値は6バイト
  for i := 0 to Length(B) -1 do
    s := s + IntToHex(B[i], 2);
  // 16進文字列として表示
  Edit2.Text := s;

  // 数値(LH反転)
  v := Integer(B[5] shl 8 + B[4]);
  if v and $8000 > 0 then v := - (v and $7FFF);
  // 小数点位置
  dp := B[0] and 3;
  // 測定値
  f := v / Power(10, dp);
  Edit1.Text  := Format('%.' + dp.ToString + 'f', [f]);
  Label1.Text := Format('%.' + dp.ToString + 'f', [f]);

  // オーバーフロー
  if B[0] and 4 > 0 then Edit1.Text := 'OL';

  // AC/DC
  case B[0] shr 4 of
     1,9: u := 'DC';
     5: if B[1] and 1 = 0 then u := 'AC';
     6,13: u := 'AC';
    10: if B[1] and 3 = 0 then u := 'DC';
    14: if B[1] and 3 = 0 then u := 'AC';
  end;
  Edit1.Text := u + ' '+ Edit1.Text;

  // 単位
  case B[0] shr 4 of
     1: u := 'mV'; // DC
     2:      if B[1] and 3 = 3 then u := 'hFE'
        else if B[1] and 2 > 0 then u := '℃'
        else if B[1] and 1 > 0 then begin
          if B[0] and 8 > 0 then u := 'KΩ'
          else u := 'Ω';
        end;
     3: if B[1] and 1 > 0 then u := 'MΩ';
     4: if B[1] and 1 > 0 then u := 'nF';
     5: if B[1] and 1 > 0 then u := 'μF'
        else u := 'mV'; // AC
     6: u := 'V'; // AC
     9: if B[0] and 8 = 8 then u := 'mA' // DC
        else u := 'μA'; // DC
    10:      if B[1] and 2 > 0 then u := 'Diode'
        else if B[1] and 1 > 0 then u := 'Hz'
        else u := 'A'; // DC
    13: if B[0] and 8 = 8 then u := 'mA' // AC
        else u := 'μA';  // AC
    14:      if B[1] and 2 > 0 then u := 'Beep'
        else if B[1] and 1 > 0 then u := '%'
        else u := 'A'; // AC
  end;
  Edit1.Text := Edit1.Text + ' ' + u;

  if B[2] and 1 > 0 then
    Edit1.Text := Edit1.Text + ' HOLD';
  if B[2] and 4 > 0 then
    Edit1.Text := Edit1.Text + ' AUTO';
  if B[2] and 32 = 32 then
    Edit1.Text := Edit1.Text + ' MAX';
  if B[2] and 16 = 16 then
    Edit1.Text := Edit1.Text + ' MIN';
  if B[2] and 2 = 2 then
    Edit1.Text := Edit1.Text + ' Δ';
end;

// デバイス検索終了
procedure TForm2.BluetoothLE1EndDiscoverDevices(const Sender: TObject;
  const ADeviceList: TBluetoothLEDeviceList);
var
  i : integer;
begin
  if ADeviceList.Count > 0 then begin
    for i := 0 to ADeviceList.Count - 1 do begin
      Memo1.Lines.Add(ADeviceList[i].DeviceName);
      if ADeviceList[i].DeviceName = BDMName then begin
        // デバイスを保持
        fBDMDevice := ADeviceList[i];
        // サービスの検索を開始
        if not ADeviceList[i].DiscoverServices then begin
          ShowMessage('サービスは使用できません.');
        end;
      end;
    end;
  end;
end;

// サービス検索終了
procedure TForm2.BluetoothLE1EndDiscoverServices(const Sender: TObject;
  const AServiceList: TBluetoothGattServiceList);
var
  i : integer;
  NotifyCharact : TBluetoothGattCharacteristic;
begin
  fBDMService := nil;
  if AServiceList.Count > 0 then begin
    for i := 0 to AServiceList.Count -1 do begin
      Memo1.Lines.Add(AServiceList[i].UUID.ToString);
      if AServiceList[i].UUID = BDMService then begin
        // サービスを保持
        fBDMService := AServiceList[i];
        Break;
      end;
    end;
  end;
  if fBDMService <> nil then begin
    for i := 0 to fBDMService.Characteristics.Count -1 do begin
      if fBDMService.Characteristics[i].UUID = BDMNotify then begin
        // 通知を設定
        NotifyCharact := fBDMService.Characteristics[i];
        fBDMDevice.SetCharacteristicNotification(NotifyCharact, true);
        break;
      end;
    end;
  end;
end;

// BLE 検索、接続
procedure TForm2.Button1Click(Sender: TObject);
begin
  BluetoothLE1.Enabled := True;
  // BLE デバイスの検索を開始
  BluetoothLE1.DiscoverDevices(500);
end;

end.