OMRONのUPSの状態を取得する

C#でOMRON(オムロン)製のUPSの状態を取得するコードを紹介します。

事前準備

こちらの記事を参照して、OMRONのUPSライブラリをダウンロードします。

プログラム

プロジェクトへのライブラリの追加

Visual Studioを起動し、Windows フォームアプリケーションを作成します。

ダウンロードしたOMRON UPSライブラリのZIPファイルを展開し、ライブラリがあるフォルダを開きます。"OmronUpsApi.dll" ファイルをVisual Studio のソリューションエクスプローラーなどにドラッグ&ドロップしてプロジェクトに追加します。



ソリューションエクスプローラーで追加した"OmronUpsApi.dll"の項目をクリックして選択します。ソリューションエクスプローラーの下部のプロパティウィンドウの[出力ディレクトリにコピー]の値を"常にコピーする"に設定します。

Microsoft.VisualBasic アセンブリの参照追加

Microsoft.VisualBasicアセンブリを参照に追加します。ソリューションエクスプローラーのウィンドウのプロジェクトのノードの子ノードの[参照]ノードをクリックして選択し、右クリックします。ポップアップメニューの[参照の追加]をクリックします。


参照の追加ダイアログで、Microsoft.VisualBasic アセンブリを選択して参照を追加します。参照が追加されると[参照]ノード内に "Micorosft.VisualBasic"アセンブリの項目が追加されます。

UI

下図のフォームを作成します。フォームにボタンを1つ、Multilineプロパティを"true"に設定した複数行テキストボックスを1つ配置します。

コード

下記のコードを記述します。
FormMain.cs (フォームのコード)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ApiCallDemo
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void FormMain_Load(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
      int lReturn = OmronUpsLib.ue_AutoFindUPS();

      if (lReturn <= 256 & lReturn >= 1) {
        int port = lReturn;
        textBox1.Text += "Com Port:" + port.ToString() + "\r\n";

        // Open communicatin port
        lReturn = OmronUpsLib.ue_OpenConnection(port);

        if (OmronUpsLib.ERROR_UPS_SUCCESSFUL == lReturn) {
          textBox1.Text += "Connection Open\r\n";

          // Get UPS status and battery status
          lReturn = GetUpsStatus();

          OmronUpsLib.ue_CloseConnection(port);
        }
        else if (OmronUpsLib.ERROR_OPEN_CONNECTION_ERROR == lReturn){
          textBox1.Text += "Connection Cannot open\r\n";
        }
        else {
        }
      }
      else if (lReturn == 901) {
        textBox1.Text += "Omron UPS Not Fond\r\n";
      }
    }

    public int GetUpsStatus()
    {
      int lReturn;
      int lGroup;
      OmronUpsLib.UPS_STATUS_AND_DATA UpsStatusAndData = new OmronUpsLib.UPS_STATUS_AND_DATA();

      lGroup = 0; // Get group 1
      lReturn = OmronUpsLib.ue_GetUPSStatusAndData(lGroup, ref UpsStatusAndData);

      if (OmronUpsLib.ERROR_UPS_SUCCESSFUL == lReturn) {
        DisplayStatus(UpsStatusAndData.UPSStatus.lUpsStatus);
        DisplayBatteryStatus(UpsStatusAndData.UPSStatus.lBatteryStatus);
      }
      else {
      }
      return 0;
    }


    public void DisplayStatus(int status)
    {
      switch (status) {
        case OmronUpsLib.UPS_NORMAL:
          textBox1.Text += "status:Normal\r\n";
          break;
        case OmronUpsLib.UPS_IN_TEST:
          textBox1.Text += "status:In Test\r\n";
          break;
        case OmronUpsLib.UPS_AC_FAIL:
          textBox1.Text += "status:AC Fail\r\n";
          break;
        case OmronUpsLib.UPS_BATTERY_LOW:
          textBox1.Text += "status:Battery Low\r\n";
          break;
        case OmronUpsLib.UPS_BATTERY_EMPTY:
          textBox1.Text += "status:Battery Empty\r\n";
          break;
        case OmronUpsLib.UPS_DISCONNECT:
          textBox1.Text += "status:Disconnect\r\n";
          break;
        default:
          textBox1.Text += "status:Disconnect\r\n";
          break;
      }
    }

    public void DisplayBatteryStatus(int status)
    {
      switch (status) {
        case OmronUpsLib.BATTERY_NORMAL:
          textBox1.Text += "battery status:Normal\r\n";
          break;
        case OmronUpsLib.BATTERY_WEAK:
          textBox1.Text += "battery status:Weak\r\n";
          break;
        case OmronUpsLib.BATTERY_NONE:
          textBox1.Text += "battery status:None\r\n";
          break;
        default:
          textBox1.Text += "battery status:None\r\n";
          break;
      }
    }

  }
}

新しいクラスを作成し、下記のコードを記述します。
OmronUpsLib.cs (ライブラリのインポート)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;

namespace ApiCallDemo
{
  public static class OmronUpsLib
  {
    // Declare some structure and global variable

    // Define some macro
    // Error code
    public const short ERROR_UPS_SUCCESSFUL = 0;
    // Public Const ERROR_UPS_DISCONNECT As Short = 900
    public const short ERROR_UPS_NOT_FOUND = 901;
    public const short ERROR_ENGINE_NOT_START = 902;
    public const short ERROR_UPS_OVER_LOAD = 903;
    public const short ERROR_OUTPUT_SHORT = 904;
    public const short ERROR_INPUT_RANGE_ERROR = 905;
    public const short ERROR_FUNCTION_TEST_FAILED = 906;
    public const short ERROR_RUNTIME_TEST_FAILED = 907;
    // Public Const ERROR_TEST_IN_PROGRESS As Short = 908
    public const short ERROR_OPEN_CONNECTION_ERROR = 909;
    public const short ERROR_CLOSE_CONNECTION_ERROR = 910;
    public const short ERROR_COMMAND_NOT_SUPPORT = 911;
    public const short ERROR_ENGINE_STOP_FAILED = 912;
    public const short ERROR_RUNTIME_FAILED = 913;
    // 20040826 added 2 error code according to user's requirement
    public const short ERROR_FUNCTION_TEST_BATTERY_FAULT = 914;
    public const short ERROR_BATTERY_TEST_UPS_FAIL = 915;
    // 20040907 added 2 error code according to user's requirement
    public const short ERROR_FUNCTION_TEST_UPS_FAIL = 916;
    public const short ERROR_BATTERY_TEST_REPLACE_BATTERY = 917;
    // 20040909 added 8 error code according to user's requirement
    public const short ERROR_OUTPUT_OVER_VOLTAGE = 918;
    public const short ERROR_DC_BUS_VOLTAGE_ABNORMAL = 919;
    public const short ERROR_OVER_LOAD_TIME_OUT = 920;
    public const short ERROR_BATTERY_OVER_CHARGER = 921;
    public const short ERROR_BATTERY_UNDER_CHARGER = 922;
    public const short ERROR_OVER_TEMPERATURE = 923;
    public const short ERROR_FAN_FAIL = 924;
    public const short ERROR_TX_FAIL = 925;


    // Define UPS Engine status
    public const short UPS_ENGINE_START = 1;
    public const short UPS_ENGINE_STOP = 0;

    // Define connection status
    public const short CONNECTION_OPEN = 1;
    public const short CONNECTION_CLOSE = 0;

    // Define UPS status and battery status
    // UPS Status
    public const short UPS_NORMAL = 0;
    public const short UPS_IN_TEST = 1;
    public const short UPS_AC_FAIL = 2;
    public const short UPS_BATTERY_LOW = 3;
    public const short UPS_BATTERY_EMPTY = 4;
    public const short UPS_DISCONNECT = 5;

    // Battery Status
    public const short BATTERY_NORMAL = 0;
    public const short BATTERY_WEAK = 1;
    public const short BATTERY_NONE = 2;

    //Define some structure for getting UPS status and data from API
    [StructLayout(LayoutKind.Sequential)]
    public struct UPS_STATUS
    {
      public int lUpsStatus;        // 0 = Normal
                                    // 1 = In Function Test or Battery Test
                                    // 2 = Backup Mode(AC Fail)
                                    // 3 = Battery Low
                                    // 4 = Battery Empty(Output Off)
                                    // Priority: 4 > 3 > 2 > 1 > 0
                                    // <FieldOffset(4)> 
      public int lBatteryStatus;        // 0 = Normal 1 = Battery Weak
    }


    //The range of array in VB must define 1 less than VC's defination
    //e.g VC defination              szInputVoltage[10]
    //VB's defination for it must be byInputVoltage(9)
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct UPS_DATA
    {
      [VBFixedString(10)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
      public string byInputVoltage;
      [VBFixedString(10)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
      public string byOutputVoltage;
      [VBFixedString(10)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
      public string byOutputLoad;
      [VBFixedString(10)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
      public string byInputFrequency;
      [VBFixedString(10)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
      public string byBatteryVoltage;
      [VBFixedString(10)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
      public string byInternalTemperature;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct UPS_STATUS_AND_DATA
    {
      [MarshalAs(UnmanagedType.Struct)]
      public UPS_STATUS UPSStatus;
      [MarshalAs(UnmanagedType.Struct)]
      public UPS_DATA UPSData;
    }

    // Boolean type in VC must declare as Long in VB
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct UPS_SETTING_DATA
    {
      [VBFixedString(10)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
      public string byInputFaultVoltage;
      // <VBFixedArray(10)> Dim byInputFaultVoltage() As Byte ' Format: +++.+(V)
      public int bBuzzerSetting; // 0 = ON; 1 = OFF
      public int bBatteryAutoTestSetting; // 0 = ON; 1 = OFF
      public int bUPSRebootSetting; // 0 = ON; 1 = OFF
      public int lCommunicationTiming; // +++(msec)
      public int lOutputVoltageMode; // 0 = 100V; 1 = 110V; 2 = 115V; 3 = 120V
      public int bInputSensitivityMode; // 0 = Standard; 1 = Low sensitivity
      public int bOutputForOutletB; // 0 = start mode; 1 = stop mode
      public int bOutputForOutletC; // 0 = start mode; 1 = stop mode
      public int bColdStartSetting; // 0 = OFF; 1 = ON ->New BX
      public int l4WeekCounter; // +++++(min) -> New BX
    }


    //Get the status and data from UPS
    //UPGRADE_WARNING: struct UPS_SETTING_DATA may require marshal property as a parameter of this declare
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_GetUPSStatusAndData(int lGroup, [MarshalAs(UnmanagedType.Struct)] ref UPS_STATUS_AND_DATA pUpsStatusAndData);
    //<MarshalAs(UnmanagedType.LPStruct)> 

    // Get the setting data from UPS
    // UPGRADE_WARNING: struct UPS_SETTING_DATA may require marshal property as a parameter of this declare
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_GetUPSSettingData([MarshalAs(UnmanagedType.Struct)] ref UPS_SETTING_DATA pUPSSettingData);

    // polling UPS information automatically
    // UPGRADE_WARNING: struct UPS_SETTING_DATA may require marshal property as a parameter of this declare
    // 20040827 removed ue_PollingUPSInformation
    // Declare Function ue_PollingUPSInformation Lib "OmronUpsAPI" (ByVal lGroup As Integer, <MarshalAs(UnmanagedType.Struct)> ByRef pUpsStatusAndData As UPS_STATUS_AND_DATA) As Integer

    // Start UPS test
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_UPSTestStart(int lTestMode);

    // Shutdown UPS
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_ShutdownUPS(int lShutdownMode, int lShutdownDelayTime, int lTurnOnDelayTime);

    // Open a COM port to communicate with UPS.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_OpenConnection(int lComPortNumber);

    // Close a COM port.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_CloseConnection(int lComPortNumber);

    // Start the Engine for polling UPS status.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_StartEngine();

    // Stop the Engine.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_StopEngine();

    // Send some commands to UPS by API.
    // 20040827 added a parameter strReturn
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_SendCommandToUPS(string strCommand, string strReturn);

    // Find UPS with COM port automatically.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_AutoFindUPS();

    // Set UPS buzzer mode.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_BuzzerSetting(int bMode);

    // Set Battery Auto Test ON/OFF.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_BatteryAutoTestSetting(int bMode);

    // Set UPS Auto Reboot mode.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_UPSAutoRebootSetting(int bMode);

    // Change communication timing between UPS and DLL.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_ChangeCommunicationTiming(int lCommunicationTiming);

    // Set UPS Output Voltage mode.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_OutputVoltageMode(int lMode);

    // Set UPS input sensitivity mode.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_InputSensitivityMode(int lMode);

    // Set UPS Backup Time value -> New BX.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_BackupTime(int lBackupTime);

    // Start UPS Output for outlet.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_OutputStartForOutlet(int lOutlet);

    // Stop UPS Output for outlet.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_OutputStopForOutlet(int lOutlet);

    // Set UPS Cold Start mode -> New BX.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_ColdStartMode(int bMode);

    // Set the 4 weeks counter value -> New BX.
    [System.Runtime.InteropServices.DllImport("OmronUpsAPI")]
    public static extern int ue_4WeeksCounterSet(int lCounterValue);

  }
}

解説

"OmronUpsLib.cs"は"OmronUpsApi.dll"に実装されている関数(API)のインポートのコードになります。

フォームのボタンがクリックされると下記のコードを実行します。
最初にue_AutoFindUPS() 関数を呼び出し、UPSと接続されているポート番号を検索します。戻り値にポート番号が返ります。UPSが無い場合はポート番号は返却されず、ERROR_OPEN_CONNECTION_ERROR (=901) が返却されます。
ポート番号が取得できた場合は、ue_OpenConnection()関数を呼び出し、UPSと接続をします。接続が成功すると ue_OpenConnection() 関数の戻り値として ERROR_UPS_SUCCESSFUL が返ります。接続に成功した場合は、テキストボックスに接続が成功した旨のメッセージを表示し、GetUpsStatus() メソッドを呼び出します。処理完了後は、CloseConnection()関数を呼び出し接続を閉じます。
  private void button1_Click(object sender, EventArgs e)
  {
    int lReturn = OmronUpsLib.ue_AutoFindUPS();

    if (lReturn <= 256 & lReturn >= 1) {
      int port = lReturn;
      textBox1.Text += "Com Port:" + port.ToString() + "\r\n";

      // Open communicatin port
      lReturn = OmronUpsLib.ue_OpenConnection(port);

      if (OmronUpsLib.ERROR_UPS_SUCCESSFUL == lReturn) {
        textBox1.Text += "Connection Open\r\n";

        // Get UPS status and battery status
        lReturn = GetUpsStatus();

        OmronUpsLib.ue_CloseConnection(port);
      }
      else if (OmronUpsLib.ERROR_OPEN_CONNECTION_ERROR == lReturn){
        textBox1.Text += "Connection Cannot open\r\n";
      }
      else {
      }
    }
    else if (lReturn == 901) {
      textBox1.Text += "Omron UPS Not Fond\r\n";
    }
  }

GetUpsStatusメソッドでは下記のコードを実行します。初めに、UPS_STATUS_AND_DATA 構造体を準備します。その後、ue_GetUPSStatusAndData() 関数を呼び出します。今回はUPSの状態とバッテリー状態を取得するため、第一引数の uGroupの値は "0" を与えます。第二引数にUPSの状態を取得するための UPS_STATUS_AND_DATA 構造体を与えます。状態の取得に成功すると、ue_GetUPSStatusAndDataの戻り値は ERROR_UPS_SUCCESSFUL が返ります。状態の取得に成功した際の状態の値はue_GetUPSStatusAndData()関数の第二引数のUPS_STATUS_AND_DATA 構造体に代入されています。DisplayStatus(), DisplayBatteryStatus() メソッドを呼び出し、UPSのステータスをテキストボックスに表示します。
  public int GetUpsStatus()
  {
    int lReturn;
    int lGroup;
    OmronUpsLib.UPS_STATUS_AND_DATA UpsStatusAndData = new OmronUpsLib.UPS_STATUS_AND_DATA();

    lGroup = 0; // Get group 1
    lReturn = OmronUpsLib.ue_GetUPSStatusAndData(lGroup, ref UpsStatusAndData);

    if (OmronUpsLib.ERROR_UPS_SUCCESSFUL == lReturn) {
      DisplayStatus(UpsStatusAndData.UPSStatus.lUpsStatus);
      DisplayBatteryStatus(UpsStatusAndData.UPSStatus.lBatteryStatus);
    }
    else {
    }
    return 0;
  }

下記のDisplayStatus(), DisplayBatteryStatus() では引数の値に応じてテキストボックスにUPSの状態値を表示します。
public void DisplayStatus(int status)
{
  switch (status) {
    case OmronUpsLib.UPS_NORMAL:
      textBox1.Text += "status:Normal\r\n";
      break;
    case OmronUpsLib.UPS_IN_TEST:
      textBox1.Text += "status:In Test\r\n";
      break;
    case OmronUpsLib.UPS_AC_FAIL:
      textBox1.Text += "status:AC Fail\r\n";
      break;
    case OmronUpsLib.UPS_BATTERY_LOW:
      textBox1.Text += "status:Battery Low\r\n";
      break;
    case OmronUpsLib.UPS_BATTERY_EMPTY:
      textBox1.Text += "status:Battery Empty\r\n";
      break;
    case OmronUpsLib.UPS_DISCONNECT:
      textBox1.Text += "status:Disconnect\r\n";
      break;
    default:
      textBox1.Text += "status:Disconnect\r\n";
      break;
  }
}

public void DisplayBatteryStatus(int status)
{
  switch (status) {
    case OmronUpsLib.BATTERY_NORMAL:
      textBox1.Text += "battery status:Normal\r\n";
      break;
    case OmronUpsLib.BATTERY_WEAK:
      textBox1.Text += "battery status:Weak\r\n";
      break;
    case OmronUpsLib.BATTERY_NONE:
      textBox1.Text += "battery status:None\r\n";
      break;
    default:
      textBox1.Text += "battery status:None\r\n";
      break;
  }
}

実行結果

OMRONのUPSの電源プラグを接続し、UPSとプログラムを実行するPCとをUSBケーブルで接続します。PC側でOMRONのUPSを認識できれば利用可能状態になります。
Windows 10の場合は設定画面の[Bluetgooth とその他のデバイス]画面の[その他のデバイス]セクションにOMRONのUPSの機器名が表示されます。下図では"BY50S"の機器名が表示されています。


プロジェクトを実行します。下図のウィンドウが表示されます。


[Connect & Get Status]ボタンをクリックします。UPSの電源プラグがコンセントに接続されているが、UPSの電源がONになっていない場合は、下図の結果となります。statusの値が"Battery Empty"になります。


続いて、UPSの電源プラグをコンセントから引き抜いた場合、または、PCと接続しているUSBケーブルを抜いてしまった状態で、[Connect & Get Status]ボタンをクリックします。下図の画面が表示されます。電源供給が無い、あるいは、接続されていない状態のため、UPSが見つからない旨のメッセージが表示されます。


UPSの電源プラグを接続し、UPS本体の電源をONにします。UPSの電源表示がONになったことを確認してから、[Connect & Get Status]ボタンをクリックします。下図の画面が表示されます。UPSが利用可能状態になっているため、status の値が "Normal" になります。


UPSの電源がONの状態で、電源プラグをコンセントから引き抜きます。UPSへの電源供給が途絶えるため、UPSからビープ音が鳴ります。この状態で、[Connect & Get Status]ボタンをクリックします。下図の画面が表示されます。電源供給がなくなった状態のため、status の値が "AC Fail" になります。

UPSの状態をプログラムで取得することができました。

著者
かつて日本を代表したスーパーエンジニア (自称)
ハードウェア、電気設備、ガーデニング関係の記事を担当。
作成日: 2018-08-25
Copyright © iPentec all rights reserverd.