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つ配置します。
コード
下記のコードを記述します。
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;
}
}
}
}
新しいクラスを作成し、下記のコードを記述します。
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の状態をプログラムで取得することができました。
著者
かつて日本を代表したスーパーエンジニア (自称)
ハードウェア、電気設備、ガーデニング関係の記事を担当。