
// WS-POS version 1.3 参照実装
// 2013/05/23 13:39:35

using UnifiedPOS.SpeechSynthesis.V1_4;
using System;
using System.Collections.Generic;

using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Threading;
using WSPOSInitiative.Common;
using OpenPOS.Extension;
using static System.Net.Mime.MediaTypeNames;

namespace WSPOSInitiative.SpeechSynthesis
{
    /// <summary>
    /// SpeechSynthesisの参照実装基底クラス
    /// </summary>
    public class SpeechSynthesisServiceProviderBehaviorCore : ServiceProviderBehavior, UnifiedPOS.SpeechSynthesis.V1_4.SpeechSynthesis, IDisposable
    {
        #region SpeechSynthesis Enumration Converter

        private static Dictionary<Enum, Enum> Convert = new Dictionary<Enum, Enum>()
            {
                { Microsoft.PointOfService.PowerReporting.Advanced, PowerReporting.PR_ADVANCED },
                { Microsoft.PointOfService.PowerReporting.None, PowerReporting.PR_NONE },
                { Microsoft.PointOfService.PowerReporting.Standard, PowerReporting.PR_STANDARD },
                { PowerReporting.PR_ADVANCED, Microsoft.PointOfService.PowerReporting.Advanced },
                { PowerReporting.PR_NONE, Microsoft.PointOfService.PowerReporting.None },
                { PowerReporting.PR_STANDARD, Microsoft.PointOfService.PowerReporting.Standard },

                { Microsoft.PointOfService.PowerNotification.Disabled, PowerNotification.PN_DISABLED },
                { Microsoft.PointOfService.PowerNotification.Enabled, PowerNotification.PN_ENABLED},
                { PowerNotification.PN_DISABLED, Microsoft.PointOfService.PowerNotification.Disabled },
                { PowerNotification.PN_ENABLED, Microsoft.PointOfService.PowerNotification.Enabled },

                { Microsoft.PointOfService.PowerState.Off, PowerState.PS_OFF},
                { Microsoft.PointOfService.PowerState.Offline, PowerState.PS_OFFLINE },
                { Microsoft.PointOfService.PowerState.OffOffline, PowerState.PS_OFF_OFFLINE },
                { Microsoft.PointOfService.PowerState.Online, PowerState.PS_ONLINE },
                { Microsoft.PointOfService.PowerState.Unknown, PowerState.PS_UNKNOWN },
                { PowerState.PS_OFF, Microsoft.PointOfService.PowerState.Off },
                { PowerState.PS_OFFLINE, Microsoft.PointOfService.PowerState.Offline },
                { PowerState.PS_OFF_OFFLINE, Microsoft.PointOfService.PowerState.OffOffline },
                { PowerState.PS_ONLINE, Microsoft.PointOfService.PowerState.Online },
                { PowerState.PS_UNKNOWN, Microsoft.PointOfService.PowerState.Unknown },

                { Microsoft.PointOfService.ControlState.Busy, ControlState.S_BUSY },
                { Microsoft.PointOfService.ControlState.Closed, ControlState.S_CLOSED },
                { Microsoft.PointOfService.ControlState.Error, ControlState.S_ERROR },
                { Microsoft.PointOfService.ControlState.Idle, ControlState.S_IDLE },
                { ControlState.S_BUSY, Microsoft.PointOfService.ControlState.Busy },
                { ControlState.S_CLOSED, Microsoft.PointOfService.ControlState.Closed },
                { ControlState.S_ERROR, Microsoft.PointOfService.ControlState.Error },
                { ControlState.S_IDLE, Microsoft.PointOfService.ControlState.Idle },

                { Microsoft.PointOfService.HealthCheckLevel.External, HealthCheckLevel.CH_EXTERNAL },
                { Microsoft.PointOfService.HealthCheckLevel.Interactive, HealthCheckLevel.CH_INTERACTIVE },
                { Microsoft.PointOfService.HealthCheckLevel.Internal, HealthCheckLevel.CH_INTERNAL },
                { HealthCheckLevel.CH_EXTERNAL, Microsoft.PointOfService.HealthCheckLevel.External },
                { HealthCheckLevel.CH_INTERACTIVE, Microsoft.PointOfService.HealthCheckLevel.Interactive },
                { HealthCheckLevel.CH_INTERNAL, Microsoft.PointOfService.HealthCheckLevel.Internal },

                { Microsoft.PointOfService.CompareFirmwareResult.Different, CompareFirmwareResult.CFV_FIRMWARE_DIFFERENT },
                { Microsoft.PointOfService.CompareFirmwareResult.Newer, CompareFirmwareResult.CFV_FIRMWARE_NEWER },
                { Microsoft.PointOfService.CompareFirmwareResult.Older, CompareFirmwareResult.CFV_FIRMWARE_OLDER },
                { Microsoft.PointOfService.CompareFirmwareResult.Same, CompareFirmwareResult.CFV_FIRMWARE_SAME },
                { Microsoft.PointOfService.CompareFirmwareResult.Unknown, CompareFirmwareResult.CFV_FIRMWARE_UNKNOWN },
                { CompareFirmwareResult.CFV_FIRMWARE_DIFFERENT, Microsoft.PointOfService.CompareFirmwareResult.Different },
                { CompareFirmwareResult.CFV_FIRMWARE_NEWER, Microsoft.PointOfService.CompareFirmwareResult.Newer },
                { CompareFirmwareResult.CFV_FIRMWARE_OLDER, Microsoft.PointOfService.CompareFirmwareResult.Older },
                { CompareFirmwareResult.CFV_FIRMWARE_SAME, Microsoft.PointOfService.CompareFirmwareResult.Same },
                { CompareFirmwareResult.CFV_FIRMWARE_UNKNOWN, Microsoft.PointOfService.CompareFirmwareResult.Unknown },

                { Microsoft.PointOfService.ErrorCode.Busy, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_BUSY },
                { Microsoft.PointOfService.ErrorCode.Claimed, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_CLAIMED },
                { Microsoft.PointOfService.ErrorCode.Closed, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_CLOSED },
                { Microsoft.PointOfService.ErrorCode.Deprecated, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_DEPRECATED },
                { Microsoft.PointOfService.ErrorCode.Disabled, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_DISABLED },
                { Microsoft.PointOfService.ErrorCode.Exists, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_EXISTS },
                { Microsoft.PointOfService.ErrorCode.Extended, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_EXTENDED },
                { Microsoft.PointOfService.ErrorCode.Failure, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_FAILURE },
                { Microsoft.PointOfService.ErrorCode.Illegal, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_ILLEGAL },
                { Microsoft.PointOfService.ErrorCode.NoExist, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOEXIST },
                { Microsoft.PointOfService.ErrorCode.NoHardware, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOHARDWARE },
                { Microsoft.PointOfService.ErrorCode.NoService, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOSERVICE },
                { Microsoft.PointOfService.ErrorCode.NotClaimed, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOTCLAIMED },
                { Microsoft.PointOfService.ErrorCode.Offline, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_OFFLINE },
                //{ Microsoft.PointOfService.ErrorCode.Success, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.SUCCESS },
                { Microsoft.PointOfService.ErrorCode.Timeout, UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_TIMEOUT },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_BUSY, Microsoft.PointOfService.ErrorCode.Busy },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_CLAIMED, Microsoft.PointOfService.ErrorCode.Claimed },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_CLOSED, Microsoft.PointOfService.ErrorCode.Closed },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_DEPRECATED, Microsoft.PointOfService.ErrorCode.Deprecated },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_DISABLED, Microsoft.PointOfService.ErrorCode.Disabled },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_EXISTS, Microsoft.PointOfService.ErrorCode.Exists },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_EXTENDED, Microsoft.PointOfService.ErrorCode.Extended },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_FAILURE, Microsoft.PointOfService.ErrorCode.Failure },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_ILLEGAL, Microsoft.PointOfService.ErrorCode.Illegal },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOEXIST, Microsoft.PointOfService.ErrorCode.NoExist },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOHARDWARE, Microsoft.PointOfService.ErrorCode.NoHardware },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOSERVICE, Microsoft.PointOfService.ErrorCode.NoService },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_NOTCLAIMED, Microsoft.PointOfService.ErrorCode.NotClaimed },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_OFFLINE, Microsoft.PointOfService.ErrorCode.Offline },
                //{ UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.SUCCESS, Microsoft.PointOfService.ErrorCode.Success },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorCode.E_TIMEOUT, Microsoft.PointOfService.ErrorCode.Timeout },

            };

        private static Dictionary<Enum, Enum> EventConvert = new Dictionary<Enum, Enum>()
            {
                { Microsoft.PointOfService.ErrorCode.Busy, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_BUSY },
                { Microsoft.PointOfService.ErrorCode.Claimed, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_CLAIMED },
                { Microsoft.PointOfService.ErrorCode.Closed, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_CLOSED },
                { Microsoft.PointOfService.ErrorCode.Deprecated, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_DEPRECATED },
                { Microsoft.PointOfService.ErrorCode.Disabled, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_DISABLED },
                { Microsoft.PointOfService.ErrorCode.Exists, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_EXISTS },
                { Microsoft.PointOfService.ErrorCode.Extended, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_EXTENDED },
                { Microsoft.PointOfService.ErrorCode.Failure, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_FAILURE },
                { Microsoft.PointOfService.ErrorCode.Illegal, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_ILLEGAL },
                { Microsoft.PointOfService.ErrorCode.NoExist, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOEXIST },
                { Microsoft.PointOfService.ErrorCode.NoHardware, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOHARDWARE },
                { Microsoft.PointOfService.ErrorCode.NoService, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOSERVICE },
                { Microsoft.PointOfService.ErrorCode.NotClaimed, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOTCLAIMED },
                { Microsoft.PointOfService.ErrorCode.Offline, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_OFFLINE },
                //{ Microsoft.PointOfService.ErrorCode.Success, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.SUCCESS },
                { Microsoft.PointOfService.ErrorCode.Timeout, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_TIMEOUT },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_BUSY, Microsoft.PointOfService.ErrorCode.Busy },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_CLAIMED, Microsoft.PointOfService.ErrorCode.Claimed },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_CLOSED, Microsoft.PointOfService.ErrorCode.Closed },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_DEPRECATED, Microsoft.PointOfService.ErrorCode.Deprecated },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_DISABLED, Microsoft.PointOfService.ErrorCode.Disabled },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_EXISTS, Microsoft.PointOfService.ErrorCode.Exists },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_EXTENDED, Microsoft.PointOfService.ErrorCode.Extended },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_FAILURE, Microsoft.PointOfService.ErrorCode.Failure },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_ILLEGAL, Microsoft.PointOfService.ErrorCode.Illegal },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOEXIST, Microsoft.PointOfService.ErrorCode.NoExist },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOHARDWARE, Microsoft.PointOfService.ErrorCode.NoHardware },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOSERVICE, Microsoft.PointOfService.ErrorCode.NoService },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_NOTCLAIMED, Microsoft.PointOfService.ErrorCode.NotClaimed },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_OFFLINE, Microsoft.PointOfService.ErrorCode.Offline },
                //{ UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.SUCCESS, Microsoft.PointOfService.ErrorCode.Success },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode.E_TIMEOUT, Microsoft.PointOfService.ErrorCode.Timeout },

                { Microsoft.PointOfService.ErrorLocus.Output, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorLocus.EL_OUTPUT },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorLocus.EL_OUTPUT, Microsoft.PointOfService.ErrorLocus.Output },

                { Microsoft.PointOfService.ErrorResponse.Clear, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorResponse.ER_CLEAR },
                { Microsoft.PointOfService.ErrorResponse.Retry, UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorResponse.ER_RETRY },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorResponse.ER_CLEAR, Microsoft.PointOfService.ErrorResponse.Clear },
                { UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorResponse.ER_RETRY, Microsoft.PointOfService.ErrorResponse.Retry },

                // Long Polling時の受信の名前空間はデバイスの名前空間にEventsがサフィックスされない
                // Events are not suffixed to the name space of event class which is received by PollForUPOSEvent
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorResponse.ER_CLEAR, Microsoft.PointOfService.ErrorResponse.Clear },
                { UnifiedPOS.SpeechSynthesis.V1_4.ErrorResponse.ER_RETRY, Microsoft.PointOfService.ErrorResponse.Retry },
            };

        #endregion

        /// <summary>
        /// 派生クラスからコンストラクタに渡されるDeviceControlDescriptionを格納
        /// </summary>
        private string _deviceControlDescription;

        /// <summary>
        /// 派生クラスからコンストラクタに渡されるDeviceControlVersionを格納
        /// </summary>
        private UposVersion _deviceControlVersion;

        /// <summary>
        /// 派生クラスからコンストラクタに渡されるWS-POSVersionを格納
        /// </summary>
        private UposVersion _wsposVersion;




        #region Constructor

        /// <summary>
        /// 呼び出せないようにprivateで宣言されています
        /// It is declared as private so that it cannot call. 
        /// </summary>
        private SpeechSynthesisServiceProviderBehaviorCore()
        {
        }

        /// <summary>
        /// コンストラクタ
        /// Constructor
        /// </summary>
        /// <param name="deviceControlDescription">DeviceControlDescription string</param>
        /// <param name="deviceControlVersion">Version value of DeviceControlVersion</param>
        /// <param name="wsposVersion">Version value of WS-POS</param>
        /// <param name="providerSessionTimeoutCheckPeriod">プロバイダのセッションタイムアウトをチェックする間隔（秒）| Interval to check the session timeout of the provider (second)</param>
        public SpeechSynthesisServiceProviderBehaviorCore(string deviceControlDescription, UposVersion deviceControlVersion, UposVersion wsposVersion, int providerSessionTimeoutCheckPeriod)
            : base(providerSessionTimeoutCheckPeriod)
        {
            _deviceControlDescription = deviceControlDescription;
            _deviceControlVersion = deviceControlVersion;
            _wsposVersion = wsposVersion;
        }

        #endregion

        #region SpeechSynthesis Member

        #region SpeechSynthesis Properties

        public virtual int GetOutputID(string ConsumerID)
        {
            try
            {
                int value = 0;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).OutputId;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual PowerReporting GetCapPowerReporting(string ConsumerID)
        {
            try
            {
                PowerReporting value = PowerReporting.PR_NONE;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = (PowerReporting)Convert[ConcretizationDevice(sessionContext.Device).CapPowerReporting];
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual bool GetCapStatisticsReporting(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).CapStatisticsReporting;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual bool GetCapUpdateStatistics(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).CapUpdateStatistics;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual string GetCheckHealthText(string ConsumerID)
        {
            try
            {
                string value = null;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).CheckHealthText;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual bool GetClaimed(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).Claimed;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual bool GetDeviceEnabled(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).DeviceEnabled;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual void SetDeviceEnabled(string ConsumerID, bool DeviceEnabled)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    ConcretizationDevice(sessionContext.Device).DeviceEnabled = DeviceEnabled;
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual bool GetFreezeEvents(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).FreezeEvents;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual void SetFreezeEvents(string ConsumerID, bool FreezeEvents)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    ConcretizationDevice(sessionContext.Device).FreezeEvents = FreezeEvents;
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual PowerNotification GetPowerNotify(string ConsumerID)
        {
            try
            {
                PowerNotification value = PowerNotification.PN_DISABLED;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = (PowerNotification)Convert[ConcretizationDevice(sessionContext.Device).PowerNotify];
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual void SetPowerNotify(string ConsumerID, PowerNotification PowerNotify)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    ConcretizationDevice(sessionContext.Device).PowerNotify = (Microsoft.PointOfService.PowerNotification)Convert[PowerNotify];
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual PowerState GetPowerState(string ConsumerID)
        {
            try
            {
                PowerState value = PowerState.PS_UNKNOWN;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = (PowerState)Convert[ConcretizationDevice(sessionContext.Device).PowerState];
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual ControlState GetState(string ConsumerID)
        {
            try
            {
                ControlState value = ControlState.S_CLOSED;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = (ControlState)Convert[ConcretizationDevice(sessionContext.Device).State];
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual bool GetCapCompareFirmwareVersion(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).CapCompareFirmwareVersion;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }
        public virtual bool GetCapUpdateFirmware(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).CapUpdateFirmware;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual string GetDeviceControlDescription(string ConsumerID)
        {
            base.GetSessionContext(ConsumerID); // セッションタイムアウトをクリアするために取得する
            return _deviceControlDescription;
        }

        public virtual UposVersion GetDeviceControlVersion(string ConsumerID)
        {
            base.GetSessionContext(ConsumerID); // セッションタイムアウトをクリアするために取得する
            return _deviceControlVersion;
        }

        public virtual string GetDeviceServiceDescription(string ConsumerID)
        {
            try
            {
                string value = null;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).ServiceObjectDescription;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual UposVersion GetDeviceServiceVersion(string ConsumerID)
        {
            try
            {
                Version value = new Version(0, 0, 0);
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).ServiceObjectVersion;
                });
                return new UposVersion() { Build = value.Build, Major = value.Major, Minor = value.Minor };
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }

        }

        public virtual string GetPhysicalDeviceDescription(string ConsumerID)
        {
            try
            {
                string value = null;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).DeviceDescription;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual string GetPhysicalDeviceName(string ConsumerID)
        {
            try
            {
                string value = null;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    value = ConcretizationDevice(sessionContext.Device).DeviceName;
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public bool GetCapLanguage(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).CapLanguage;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public bool GetCapPitch(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).CapPitch;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public bool GetCapSpeed(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).CapSpeed;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public bool GetCapVoice(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).CapVoice;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public bool GetCapVolume(string ConsumerID)
        {
            try
            {
                bool value = false;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).CapVolume;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public string GetLanguage(string ConsumerID)
        {
            try
            {
                string value = null;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).Language;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void SetLanguage(string ConsumerID, string Language)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).Language = Language;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public LanguageList GetLanguageList(string ConsumerID)
        {
            try
            {
                LanguageList value = new LanguageList();

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value.AddRange(((ISpeechSynthesis116)device).LanguageList);
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }

                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public OutputIDList GetOutputIDList(string ConsumerID)
        {
            try
            {
                OutputIDList value = new OutputIDList();

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value.AddRange(((ISpeechSynthesis116)device).OutputIdList);
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }

                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public int GetPitch(string ConsumerID)
        {
            try
            {
                int value = 0;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).Pitch;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void SetPitch(string ConsumerID, int Pitch)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).Pitch = Pitch;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public int GetSpeed(string ConsumerID)
        {
            try
            {
                int value = 0;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).Speed;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void SetSpeed(string ConsumerID, int Speed)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).Speed = Speed;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public string GetVoice(string ConsumerID)
        {
            try
            {
                string value = null;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).Voice;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void SetVoice(string ConsumerID, string Voice)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).Voice = Voice;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public VoiceList GetVoiceList(string ConsumerID)
        {
            try
            {
                VoiceList value = new VoiceList();

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value.AddRange(((ISpeechSynthesis116)device).VoiceList);
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }

                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public int GetVolume(string ConsumerID)
        {
            try
            {
                int value = 0;

                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        value = ((ISpeechSynthesis116)device).Volume;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });

                return value;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void SetVolume(string ConsumerID, int Volume)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).Volume = Volume;
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Property not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        #endregion

        #region SpeechSynthesis Methods

        public virtual string GetEncryptedClaimedConsumerID()
        {
            try
            {
                var consumerIDs = base.GetAllSessionIDs();

                string claimedConsumerID = null;

            LOOP_START:

                foreach (var id in consumerIDs)
                {
                    try
                    {
                        if (claimedConsumerID != null)
                        {
                            break;
                        }

                        var sessionContext = base.GetSessionContext(id);
                        sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                        {
                            if (ConcretizationDevice(sessionContext.Device).Claimed)
                            {
                                claimedConsumerID = id;
                            }
                        });
                    }
                    catch (KeyNotFoundException)
                    {
                        ;// 時間差で削除された
                    }
                    catch (InvalidOperationException)
                    {
                        goto LOOP_START;// 時間差で削除された
                    }
                    catch (Microsoft.PointOfService.PosControlException)
                    {
                        ;// Closeされた
                    }
                }

                if (claimedConsumerID != null)
                {
                    return base.EncryptConsumerID(claimedConsumerID);
                }
                else
                {
                    return null;
                }
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void OpenSession(string ConsumerID, string EndpointAddress)
        {
            try
            {
                UnifiedPOS.SpeechSynthesisEvents.V1_4.SpeechSynthesisEvent deviceEvent = null;
                if (EndpointAddress != null)
                {
                    ChannelFactory<UnifiedPOS.SpeechSynthesisEvents.V1_4.SpeechSynthesisEvent> factory =
                        new ChannelFactory<UnifiedPOS.SpeechSynthesisEvents.V1_4.SpeechSynthesisEvent>("SpeechSynthesisEventPort", new EndpointAddress(EndpointAddress));

                    deviceEvent = factory.CreateChannel();
                }

                ISessionContext sessionContext = base.CreateSessionContext(ConsumerID, deviceEvent);

                sessionContext.ServiceDirectIOEvent += new EventHandler<Microsoft.PointOfService.DirectIOEventArgs>(SessionContext_ServiceDirectIOEvent);
                sessionContext.ServiceDataEvent += new EventHandler<Microsoft.PointOfService.DataEventArgs>(SessionContext_ServiceDataEvent);
                sessionContext.ServiceErrorEvent += new EventHandler<Microsoft.PointOfService.DeviceErrorEventArgs>(SessionContext_ServiceErrorEvent);
                sessionContext.ServiceOutputCompleteEvent += new EventHandler<Microsoft.PointOfService.OutputCompleteEventArgs>(SessionContext_ServiceOutputCompleteEvent);
                sessionContext.ServiceStatusUpdateEvent += new EventHandler<Microsoft.PointOfService.StatusUpdateEventArgs>(SessionContext_ServiceStatusUpdateEvent);

                foreach (ServiceEndpoint Endpoint in OperationContext.Current.Host.Description.Endpoints)
                {
                    if (Endpoint.Address.Equals(OperationContext.Current.Channel.LocalAddress))
                    {
                        ConfigDeviceBehavior ConfigDevice = Endpoint.Behaviors.Find<ConfigDeviceBehavior>();
                        if (ConfigDevice != null)
                        {
                            sessionContext.DeviceName = ConfigDevice.deviceName;
                            sessionContext.ProviderSessionTimeout = ConfigDevice.providerSessionTimeout;
                            sessionContext.EventPollingTimeout = ConfigDevice.eventPollingTimeout > 0 ? ConfigDevice.eventPollingTimeout * 1000 : ConfigDevice.eventPollingTimeout;
                            sessionContext.EventResponseTimeout = ConfigDevice.eventResponseTimeout > 0 ? ConfigDevice.eventResponseTimeout * 1000 : ConfigDevice.eventResponseTimeout;
                            sessionContext.CodePageConversion = ConfigDevice.codePageConversion;
                        }
                    }
                }

                base.AddSession(ConsumerID, sessionContext);
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void OpenDevice(string ConsumerID)
        {
            try
            {
                ISessionContext sessionContext = GetSessionContext(ConsumerID);

                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    base.OpenDeviceInSessionContext(sessionContext, "ToneIndicator", sessionContext.DeviceName);

                    var device = ConcretizationDevice(sessionContext.Device);
                    device.Open();
                    //device.DataEvent += new Microsoft.PointOfService.DataEventHandler(sessionContext.DeviceDataEventHandler);
                    device.DirectIOEvent += new Microsoft.PointOfService.DirectIOEventHandler(sessionContext.DeviceDirectIOEventHandler);
                    device.ErrorEvent += new Microsoft.PointOfService.DeviceErrorEventHandler(sessionContext.DeviceErrorEventHandler);
                    device.OutputCompleteEvent += new Microsoft.PointOfService.OutputCompleteEventHandler(sessionContext.DeviceOutputCompleteEventHandler);
                    device.StatusUpdateEvent += new Microsoft.PointOfService.StatusUpdateEventHandler(sessionContext.DeviceStatusUpdateEventHandler);

                    sessionContext.IsLegacySO = false;
                    try
                    {
                        // OPOS Legacy SO の場合は BinaryConversion を設定する。設定に成功するならば LegacySOと判断する。
                        var legacyDevice = (Microsoft.PointOfService.ILegacyControlObject)device;
                        sessionContext.IsLegacySO = true;
                        legacyDevice.BinaryConversion = Microsoft.PointOfService.BinaryConversion.Nibble;
                    }
                    catch { }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void CloseDevice(string ConsumerID)
        {
            try
            {
                ISessionContext sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    DisposeDevice(sessionContext);
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void CloseSession(string ConsumerID)
        {
            try
            {
                ISessionContext sessionContext = base.GetSessionContext(ConsumerID);
                CloseSessionResources(sessionContext);

                base.RemoveSessionContext(ConsumerID);
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }


        public virtual void ClearOutput(string ConsumerID)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    ConcretizationDevice(sessionContext.Device).ClearOutput();
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void CheckHealth(string ConsumerID, HealthCheckLevel Level)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    ConcretizationDevice(sessionContext.Device).CheckHealth((Microsoft.PointOfService.HealthCheckLevel)Convert[Level]);
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void Claim(string ConsumerID, int Timeout)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    ConcretizationDevice(sessionContext.Device).Claim(Timeout);
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual DirectIOData DirectIO(string ConsumerID, int Command, int Data, object Obj)
        {
            try
            {
                Microsoft.PointOfService.DirectIOData value = new Microsoft.PointOfService.DirectIOData();
                var sessionContext = (base.GetSessionContext(ConsumerID));
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    string artsB = (string)Obj;
                    var str = base.ConvertARTSBinaryToString(sessionContext.IsLegacySO, sessionContext.CodePageConversion, artsB);
                    value = ConcretizationDevice(sessionContext.Device).DirectIO(Command, Data, str);
                });
                return new DirectIOData() { Data = value.Data, Obj = base.ConvertStringToARTSBinary(sessionContext.IsLegacySO, sessionContext.CodePageConversion, (string)value.Object) };
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void Release(string ConsumerID)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var freezeEvents = ConcretizationDevice(sessionContext.Device).FreezeEvents;
                    ConcretizationDevice(sessionContext.Device).FreezeEvents = true;
                    base.WaitForEventHandlerReturned(sessionContext);

                    ConcretizationDevice(sessionContext.Device).Release();
                    base.DeleteAsyncTemporaryFiles(sessionContext);

                    ConcretizationDevice(sessionContext.Device).FreezeEvents = freezeEvents;
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void ResetStatistics(string ConsumerID, StatisticList StatisticsBuffer)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);

                    var value = new List<string>(); foreach (var s in StatisticsBuffer) { value.Add(s.Name); }　// .NET FW 3のため、Linq使用不可 var value = from el in StatisticsBuffer select el.Name;;
                    switch (value.Count)
                    {
                        case 0:
                            device.ResetStatistics();
                            break;
                        case 1:
                            string name = value[0];
                            switch (name)
                            {
                                case StatisticCategories.All:
                                    device.ResetStatistics(Microsoft.PointOfService.StatisticCategories.All);
                                    break;
                                case StatisticCategories.Manufacturer:
                                    device.ResetStatistics(Microsoft.PointOfService.StatisticCategories.Manufacturer);
                                    break;
                                case StatisticCategories.Upos:
                                    device.ResetStatistics(Microsoft.PointOfService.StatisticCategories.Upos);
                                    break;
                                default:
                                    device.ResetStatistic(name);
                                    break;
                            }
                            break;
                        default:
                            device.ResetStatistics(value.ToArray());
                            break;
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }


        public virtual string RetrieveStatistics(string ConsumerID, StatisticList StatisticsBuffer)
        {
            try
            {
                string res = null;
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    var value = new List<string>(); foreach (var s in StatisticsBuffer) { value.Add(s.Name); }　// .NET FW 3のため、Linq使用不可 var value = from el in StatisticsBuffer select el.Name;;
                    switch (value.Count)
                    {
                        case 0:
                            res = device.RetrieveStatistics();
                            break;
                        case 1:
                            string name = value[0];
                            switch (name)
                            {
                                case StatisticCategories.All:
                                    res = device.RetrieveStatistics(Microsoft.PointOfService.StatisticCategories.All);
                                    break;
                                case StatisticCategories.Manufacturer:
                                    res = device.RetrieveStatistics(Microsoft.PointOfService.StatisticCategories.Manufacturer);
                                    break;
                                case StatisticCategories.Upos:
                                    res = device.RetrieveStatistics(Microsoft.PointOfService.StatisticCategories.Upos);
                                    break;
                                default:
                                    res = device.RetrieveStatistic(name);
                                    break;
                            }
                            break;
                        default:
                            res = device.RetrieveStatistics(value.ToArray());
                            break;
                    }
                });
                return res;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void UpdateStatistics(string ConsumerID, StatisticList StatisticsBuffer)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    var value = new List<Microsoft.PointOfService.Statistic>(); foreach (var s in StatisticsBuffer) { value.Add(new Microsoft.PointOfService.Statistic(s.Name, s.Value)); } // var value = from el in StatisticsBuffer select new Microsoft.PointOfService.Statistic(el.Name, el.Value);
                    switch (value.Count)
                    {
                        case 0:
                            device.UpdateStatistics(value.ToArray());
                            break;
                        case 1:
                            Microsoft.PointOfService.Statistic statistic = value[0];
                            switch (statistic.Name)
                            {
                                case StatisticCategories.All:
                                    device.UpdateStatistics(Microsoft.PointOfService.StatisticCategories.All, statistic.Value);
                                    break;
                                case StatisticCategories.Manufacturer:
                                    device.UpdateStatistics(Microsoft.PointOfService.StatisticCategories.Manufacturer, statistic.Value);
                                    break;
                                case StatisticCategories.Upos:
                                    device.UpdateStatistics(Microsoft.PointOfService.StatisticCategories.Upos, statistic.Value);
                                    break;
                                default:
                                    device.UpdateStatistic(statistic.Name, statistic.Value);
                                    break;
                            }
                            break;
                        default:
                            device.UpdateStatistics(value.ToArray());
                            break;
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual CompareFirmwareResult CompareFirmwareVersion(string ConsumerID, string FirmwareFileName)
        {
            try
            {
                CompareFirmwareResult result = CompareFirmwareResult.CFV_FIRMWARE_UNKNOWN;

                UriToTempFileHelper.UriToTempFileExecuteTargetMethod(FirmwareFileName, true, (tempFileName) =>
                {
                    var sessionContext = base.GetSessionContext(ConsumerID);
                    sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                    {
                        sessionContext.TempFileNamesForDeleteWhenCloseDevice.Add(tempFileName);
                        result = (CompareFirmwareResult)Convert[ConcretizationDevice(sessionContext.Device).CompareFirmwareVersion(tempFileName)];
                    });
                });

                return result;
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }


        public virtual void UpdateFirmware(string ConsumerID, string FirmwareFileName)
        {
            try
            {
                UriToTempFileHelper.UriToTempFileExecuteTargetMethod(FirmwareFileName, false, (tempFileName) =>
                {
                    var sessionContext = base.GetSessionContext(ConsumerID);
                    sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                    {
                        sessionContext.TempFileNamesForDeleteWhenCloseDevice.Add(tempFileName);
                        ConcretizationDevice(sessionContext.Device).UpdateFirmware(tempFileName);
                    });
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual UposVersion GetWSPOSVersion()
        {
            return _wsposVersion;
        }

        public void Speak(string ConsumerID, string Text)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).Speak(Text);
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Method not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void SpeakImmediate(string ConsumerID, string Text)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).SpeakImmediate(Text);
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Method not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void StopCurrentSpeaking(string ConsumerID)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).StopCurrentSpeaking();
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Method not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public void StopSpeaking(string ConsumerID, int OutputID)
        {
            try
            {
                var sessionContext = base.GetSessionContext(ConsumerID);
                sessionContext.DeviceThread.ExecuteOnWorkerThread(() =>
                {
                    var device = ConcretizationDevice(sessionContext.Device);
                    if (device is ISpeechSynthesis116)
                    {
                        ((ISpeechSynthesis116)device).StopSpeaking(OutputID);
                    }
                    else
                    {
                        throw new Microsoft.PointOfService.PosControlException("Method not supported.", Microsoft.PointOfService.ErrorCode.Illegal, 0);
                    }
                });
            }
            catch (Microsoft.PointOfService.PosControlException pex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), pex);
                UposException uex = new UposException();
                uex.ErrorCode = (ErrorCode)Convert[pex.ErrorCode];
                uex.ErrorCodeExtended = pex.ErrorCodeExtended;
                throw new FaultException<UposException>(uex, pex.Message);
            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        #endregion

        #region SpeechSynthesis Events

        /// <summary>
        /// サービス内でのDataEventハンドラ
        /// DataEvent handler in the service
        /// </summary>
        /// <param name="sender">Sender instance</param>
        /// <param name="e">Event argument</param>
        protected override void SessionContext_ServiceDataEvent(object sender, Microsoft.PointOfService.DataEventArgs e)
        {
            try
            {
                ISessionContext sessionContext = sender as ISessionContext;

                // デバイスをCloseする際に、このイベントハンドラが実行中でないことを確認するためのフラグを設定する。
                // When Closing a device, the flag for checking that this event handler is not going.
                sessionContext.UPOSEventHandlingOnGoing = true;

                if (sessionContext.ConsumerEventPort != null)
                {
                    // 双方向通信
                    // LegacySOのSTAからのRPC呼び出しに伴うアパートメントブロックによるデッドロックを回避するため、ワーカスレッドで呼び出します。
                    // Bi-directional communication: 
                    // In order to avoid the deadlock by the apartment block accompanying the RPC call from STA of LegacySO, it is called by a worker thread. 
                    System.Threading.Thread eventCallThread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
                    {
                        var deviceEvent = ConcretizationConsumerEventPort(sessionContext.ConsumerEventPort);
                        bool isTimeoutHappened = false;
                        do
                        {
                            try
                            {
                                //deviceEvent.DataEvent(sessionContext.ConsumerID, sessionContext.Device.ToString(), e.EventId, e.TimeStamp, e.Status);
                            }
                            catch (Exception ex)
                            {
                                if (ex is TimeoutException || ex is EndpointNotFoundException)
                                {
                                    isTimeoutHappened = true;
                                    // レスポンスが帰ってこない場合、再度通知します。
                                    // タイムアウトになり続けた場合、ProviderSessionTimeout値によって
                                    // セッションが閉じられるまでこれを続けます。
                                    // When a response does not come back, it notifies again. 
                                    // When it continues being timing out, this is continued until a 
                                    // session is closed by the ProviderSessionTimeout value. 
                                    if (sessionContext.IsClosed)
                                    {
                                        base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, and session closed.");
                                        break;
                                    }
                                    base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, then retry.");
                                }
                                else
                                {
                                    break;
                                }
                            }
                        } while (isTimeoutHappened);
                    }));
                    eventCallThread.Start();
                    eventCallThread.Join();
                }
                else
                {
                    // ロングポーリング
                    // Long polling

                    // PollForUPOSEventでの待ちに対して通知する
                    // Notifying wait in PollForUPOSEvent

                    sessionContext.DeviceEventArgs = e;
                    sessionContext.DeviceEventHappened.Signal();

                    // EventResponseの呼び出しを待つ
                    // It waits for the call of EventResponse.
                    sessionContext.SetEventResponseCalled.Wait(sessionContext.EventResponseTimeout);
                }
            }
            catch (ObjectDisposedException ex)
            {
                // 待ち合わせ中にセッションが閉じた場合
                // WaitOneがObjectDisposedException例外をスローします。
                // デバイス側は異常ではないため、例外をデバイスにスローせず
                // 記録ログのみ書きます
                // When a session closes during waiting 
                // WaitOne will throw of the ObjectDisposedException exception. 
                // Since the device side is not unusual, it does not throw the exception 
                // to a device, but only writes log records. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            catch (Exception ex)
            {
                // デバイスからのイベントハンドラ内部での例外はデバイスによってハンドリングされないため
                // ログは書き込みますが例外をデバイスにスローしません
                // Since the exception inside the event handler from a device is not handled by the device, 
                // although a log writes in, it does not throw the exception to a device. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            finally
            {
                ISessionContext sessionContext = sender as ISessionContext;
                sessionContext.UPOSEventHandlingOnGoing = false;
            }
        }

        /// <summary>
        /// サービス内でのDirectIOEventハンドラ
        /// </summary>
        /// <param name="sender">送信者インスタンス</param>
        /// <param name="e">イベント引数</param>
        protected override void SessionContext_ServiceDirectIOEvent(object sender, Microsoft.PointOfService.DirectIOEventArgs e)
        {
            try
            {
                ISessionContext sessionContext = sender as ISessionContext;

                // デバイスをCloseする際に、このイベントハンドラが実行中でないことを確認するためのフラグを設定する。
                // When Closing a device, the flag for checking that this event handler is not going.
                sessionContext.UPOSEventHandlingOnGoing = true;

                if (sessionContext.ConsumerEventPort != null)
                {
                    // 双方向通信
                    // LegacySOのSTAからのRPC呼び出しに伴うアパートメントブロックによるデッドロックを回避するため、ワーカスレッドで呼び出します。
                    // Bi-directional communication: 
                    // In order to avoid the deadlock by the apartment block accompanying the RPC call from STA of LegacySO, it is called by a worker thread. 
                    System.Threading.Thread eventCallThread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
                    {
                        var deviceEvent = ConcretizationConsumerEventPort(sessionContext.ConsumerEventPort);
                        bool isTimeoutHappened = false;
                        do
                        {
                            try
                            {
                                string artsB = (string)e.Object;
                                var str = base.ConvertARTSBinaryToString(sessionContext.IsLegacySO, sessionContext.CodePageConversion, artsB);
                                var value = deviceEvent.DirectIOEvent(sessionContext.ConsumerID, sessionContext.Device.ToString(), e.EventId, e.TimeStamp, e.EventNumber, e.Data, str);
                                e.Data = value.Data;
                                e.Object = base.ConvertStringToARTSBinary(sessionContext.IsLegacySO, sessionContext.CodePageConversion, (string)value.Obj);
                            }
                            catch (Exception ex)
                            {
                                if (ex is TimeoutException || ex is EndpointNotFoundException)
                                {
                                    isTimeoutHappened = true;
                                    // レスポンスが帰ってこない場合、再度通知します。
                                    // タイムアウトになり続けた場合、ProviderSessionTimeout値によって
                                    // セッションが閉じられるまでこれを続けます。
                                    // When a response does not come back, it notifies again. 
                                    // When it continues being timing out, this is continued until a 
                                    // session is closed by the ProviderSessionTimeout value. 
                                    if (sessionContext.IsClosed)
                                    {
                                        base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, and session closed.");
                                        break;
                                    }
                                    base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, then retry.");
                                }
                                else
                                {
                                    break;
                                }
                            }
                        } while (isTimeoutHappened);
                    }));
                    eventCallThread.Start();
                    eventCallThread.Join();
                }
                else
                {
                    // ロングポーリング
                    // Long polling

                    // PollForUPOSEventでの待ちに対して通知する
                    // Notifying wait in PollForUPOSEvent

                    sessionContext.DeviceEventArgs = e;
                    sessionContext.DeviceEventHappened.Signal();

                    // EventResponseの呼び出しをまつ
                    if (sessionContext.SetEventResponseCalled.Wait(sessionContext.EventResponseTimeout))
                    {
                        DirectIOData value = sessionContext.DeviceEventResponse as DirectIOData;

                        e.Data = value.Data;
                        e.Object = base.ConvertARTSBinaryToString(sessionContext.IsLegacySO, sessionContext.CodePageConversion, (string)value.Obj);
                    }
                }
            }
            catch (ObjectDisposedException ex)
            {
                // 待ち合わせ中にセッションが閉じた場合
                // WaitOneがObjectDisposedException例外をスローします。
                // デバイス側は異常ではないため、例外をデバイスにスローせず
                // 記録ログのみ書きます
                // When a session closes during waiting 
                // WaitOne will throw of the ObjectDisposedException exception. 
                // Since the device side is not unusual, it does not throw the exception 
                // to a device, but only writes log records. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            catch (Exception ex)
            {
                // デバイスからのイベントハンドラ内部での例外はデバイスによってハンドリングされないため
                // ログは書き込みますが例外をデバイスにスローしません
                // Since the exception inside the event handler from a device is not handled by the device, 
                // although a log writes in, it does not throw the exception to a device. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            finally
            {
                ISessionContext sessionContext = sender as ISessionContext;
                sessionContext.UPOSEventHandlingOnGoing = false;
            }

        }

        /// <summary>
        /// サービス内でのErrorEvventハンドラ
        /// </summary>
        /// <param name="sender">送信者インスタンス</param>
        /// <param name="e">イベント引数</param>
        protected override void SessionContext_ServiceErrorEvent(object sender, Microsoft.PointOfService.DeviceErrorEventArgs e)
        {
            try
            {
                ISessionContext sessionContext = sender as ISessionContext;

                // デバイスをCloseする際に、このイベントハンドラが実行中でないことを確認するためのフラグを設定する。
                // When Closing a device, the flag for checking that this event handler is not going.
                sessionContext.UPOSEventHandlingOnGoing = true;

                if (sessionContext.ConsumerEventPort != null)
                {
                    // 双方向通信
                    // LegacySOのSTAからのRPC呼び出しに伴うアパートメントブロックによるデッドロックを回避するため、ワーカスレッドで呼び出します。
                    // Bi-directional communication: 
                    // In order to avoid the deadlock by the apartment block accompanying the RPC call from STA of LegacySO, it is called by a worker thread. 
                    System.Threading.Thread eventCallThread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
                    {
                        var deviceEvent = ConcretizationConsumerEventPort(sessionContext.ConsumerEventPort);
                        bool isTimeoutHappened = false;
                        do
                        {
                            try
                            {
                                var value = deviceEvent.ErrorEvent(sessionContext.ConsumerID, sessionContext.Device.ToString(), e.EventId, e.TimeStamp, (UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorCode)EventConvert[e.ErrorCode], e.ErrorCodeExtended, (UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorLocus)EventConvert[e.ErrorLocus], (UnifiedPOS.SpeechSynthesisEvents.V1_4.ErrorResponse)EventConvert[e.ErrorResponse]);
                                e.ErrorResponse = (Microsoft.PointOfService.ErrorResponse)EventConvert[value];
                            }
                            catch (Exception ex)
                            {
                                if (ex is TimeoutException || ex is EndpointNotFoundException)
                                {
                                    isTimeoutHappened = true;
                                    // レスポンスが帰ってこない場合、再度通知します。
                                    // タイムアウトになり続けた場合、ProviderSessionTimeout値によって
                                    // セッションが閉じられるまでこれを続けます。
                                    // When a response does not come back, it notifies again. 
                                    // When it continues being timing out, this is continued until a 
                                    // session is closed by the ProviderSessionTimeout value. 
                                    if (sessionContext.IsClosed)
                                    {
                                        base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, and session closed.");
                                        e.ErrorResponse = Microsoft.PointOfService.ErrorResponse.Clear;
                                        break;
                                    }
                                    base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, then retry.");
                                }
                                else
                                {
                                    break;
                                }
                            }
                        } while (isTimeoutHappened);
                    }));
                    eventCallThread.Start();
                    eventCallThread.Join();
                }
                else
                {
                    // ロングポーリング
                    // Long polling

                    // PollForUPOSEventでの待ちに対して通知する
                    // Notifying wait in PollForUPOSEvent

                    sessionContext.DeviceEventArgs = e;
                    sessionContext.DeviceEventHappened.Signal();

                    // SetEventResponseの呼び出しを待つ
                    if (sessionContext.SetEventResponseCalled.Wait(sessionContext.EventResponseTimeout))
                    {
                        ErrorResponse value = (ErrorResponse)sessionContext.DeviceEventResponse;
                        e.ErrorResponse = (Microsoft.PointOfService.ErrorResponse)EventConvert[value];
                    }
                    else
                    {
                        e.ErrorResponse = Microsoft.PointOfService.ErrorResponse.Clear;
                    }
                }
            }
            catch (ObjectDisposedException ex)
            {
                // 待ち合わせ中にセッションが閉じた場合
                // WaitOneがObjectDisposedException例外をスローします。
                // デバイス側は異常ではないため、例外をデバイスにスローせず
                // 記録ログのみ書きます
                // When a session closes during waiting 
                // WaitOne will throw of the ObjectDisposedException exception. 
                // Since the device side is not unusual, it does not throw the exception 
                // to a device, but only writes log records. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            catch (Exception ex)
            {
                // デバイスからのイベントハンドラ内部での例外はデバイスによってハンドリングされないため
                // ログは書き込みますが例外をデバイスにスローしません
                // Since the exception inside the event handler from a device is not handled by the device, 
                // although a log writes in, it does not throw the exception to a device. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            finally
            {
                ISessionContext sessionContext = sender as ISessionContext;
                sessionContext.UPOSEventHandlingOnGoing = false;
            }
        }

        /// <summary>
        /// サービス内でのOutputCompleteEventハンドラ
        /// </summary>
        /// <param name="sender">送信者インスタンス</param>
        /// <param name="e">イベント引数</param>
        protected override void SessionContext_ServiceOutputCompleteEvent(object sender, Microsoft.PointOfService.OutputCompleteEventArgs e)
        {
            try
            {
                ISessionContext sessionContext = sender as ISessionContext;

                // デバイスをCloseする際に、このイベントハンドラが実行中でないことを確認するためのフラグを設定する。
                // When Closing a device, the flag for checking that this event handler is not going.
                sessionContext.UPOSEventHandlingOnGoing = true;

                if (sessionContext.ConsumerEventPort != null)
                {
                    // 双方向通信
                    // LegacySOのSTAからのRPC呼び出しに伴うアパートメントブロックによるデッドロックを回避するため、ワーカスレッドで呼び出します。
                    // Bi-directional communication: 
                    // In order to avoid the deadlock by the apartment block accompanying the RPC call from STA of LegacySO, it is called by a worker thread. 
                    System.Threading.Thread eventCallThread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
                    {
                        var deviceEvent = ConcretizationConsumerEventPort(sessionContext.ConsumerEventPort);
                        bool isTimeoutHappened = false;
                        do
                        {
                            try
                            {
                                deviceEvent.OutputCompleteEvent(sessionContext.ConsumerID, sessionContext.Device.ToString(), e.EventId, e.TimeStamp, e.OutputId);
                            }
                            catch (Exception ex)
                            {
                                if (ex is TimeoutException || ex is EndpointNotFoundException)
                                {
                                    isTimeoutHappened = true;
                                    // レスポンスが帰ってこない場合、再度通知します。
                                    // タイムアウトになり続けた場合、ProviderSessionTimeout値によって
                                    // セッションが閉じられるまでこれを続けます。
                                    // When a response does not come back, it notifies again. 
                                    // When it continues being timing out, this is continued until a 
                                    // session is closed by the ProviderSessionTimeout value. 
                                    if (sessionContext.IsClosed)
                                    {
                                        base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, and session closed.");
                                        break;
                                    }
                                    base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, then retry.");
                                }
                                else
                                {
                                    break;
                                }
                            }
                        } while (isTimeoutHappened);
                    }));
                    eventCallThread.Start();
                    eventCallThread.Join();
                }
                else
                {
                    // ロングポーリング
                    // Long polling

                    // PollForUPOSEventでの待ちに対して通知する
                    // Notifying wait in PollForUPOSEvent

                    sessionContext.DeviceEventArgs = e;
                    sessionContext.DeviceEventHappened.Signal();

                    // SetEventResponseの呼び出しを待つ
                    sessionContext.SetEventResponseCalled.Wait(sessionContext.EventResponseTimeout);
                }
            }
            catch (ObjectDisposedException ex)
            {
                // 待ち合わせ中にセッションが閉じた場合
                // WaitOneがObjectDisposedException例外をスローします。
                // デバイス側は異常ではないため、例外をデバイスにスローせず
                // 記録ログのみ書きます
                // When a session closes during waiting 
                // WaitOne will throw of the ObjectDisposedException exception. 
                // Since the device side is not unusual, it does not throw the exception 
                // to a device, but only writes log records. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            catch (Exception ex)
            {
                // デバイスからのイベントハンドラ内部での例外はデバイスによってハンドリングされないため
                // ログは書き込みますが例外をデバイスにスローしません
                // Since the exception inside the event handler from a device is not handled by the device, 
                // although a log writes in, it does not throw the exception to a device. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            finally
            {
                ISessionContext sessionContext = sender as ISessionContext;
                sessionContext.UPOSEventHandlingOnGoing = false;
            }

        }

        /// <summary>
        /// サービス内でのStatusUpdateEventハンドラ
        /// </summary>
        /// <param name="sender">送信者インスタンス</param>
        /// <param name="e">イベント引数</param>
        protected override void SessionContext_ServiceStatusUpdateEvent(object sender, Microsoft.PointOfService.StatusUpdateEventArgs e)
        {
            try
            {
                ISessionContext sessionContext = sender as ISessionContext;

                // デバイスをCloseする際に、このイベントハンドラが実行中でないことを確認するためのフラグを設定する。
                // When Closing a device, the flag for checking that this event handler is not going.
                sessionContext.UPOSEventHandlingOnGoing = true;

                if (sessionContext.ConsumerEventPort != null)
                {
                    // 双方向通信
                    // LegacySOのSTAからのRPC呼び出しに伴うアパートメントブロックによるデッドロックを回避するため、ワーカスレッドで呼び出します。
                    // Bi-directional communication: 
                    // In order to avoid the deadlock by the apartment block accompanying the RPC call from STA of LegacySO, it is called by a worker thread. 
                    System.Threading.Thread eventCallThread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
                    {
                        var deviceEvent = ConcretizationConsumerEventPort(sessionContext.ConsumerEventPort);
                        bool isTimeoutHappened = false;
                        do
                        {
                            try
                            {
                                deviceEvent.StatusUpdateEvent(sessionContext.ConsumerID, sessionContext.Device.ToString(), e.EventId, e.TimeStamp, e.Status);
                            }
                            catch (Exception ex)
                            {
                                if (ex is TimeoutException || ex is EndpointNotFoundException)
                                {
                                    isTimeoutHappened = true;
                                    // レスポンスが帰ってこない場合、再度通知します。
                                    // タイムアウトになり続けた場合、ProviderSessionTimeout値によって
                                    // セッションが閉じられるまでこれを続けます。
                                    // When a response does not come back, it notifies again. 
                                    // When it continues being timing out, this is continued until a 
                                    // session is closed by the ProviderSessionTimeout value. 
                                    if (sessionContext.IsClosed)
                                    {
                                        base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, and session closed.");
                                        break;
                                    }
                                    base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "Network timeout when event notify, then retry.");
                                }
                                else
                                {
                                    break;
                                }
                            }
                        } while (isTimeoutHappened);
                    }));
                    eventCallThread.Start();
                    eventCallThread.Join();
                }
                else
                {
                    // ロングポーリング
                    // Long polling

                    // PollForUPOSEventでの待ちに対して通知する
                    // Notifying wait in PollForUPOSEvent

                    sessionContext.DeviceEventArgs = e;
                    sessionContext.DeviceEventHappened.Signal();

                    // SetEventResponseの呼び出しを待つ
                    sessionContext.SetEventResponseCalled.Wait(sessionContext.EventResponseTimeout);
                }
            }
            catch (ObjectDisposedException ex)
            {
                // 待ち合わせ中にセッションが閉じた場合
                // WaitOneがObjectDisposedException例外をスローします。
                // デバイス側は異常ではないため、例外をデバイスにスローせず
                // 記録ログのみ書きます
                // When a session closes during waiting 
                // WaitOne will throw of the ObjectDisposedException exception. 
                // Since the device side is not unusual, it does not throw the exception 
                // to a device, but only writes log records. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            catch (Exception ex)
            {
                // デバイスからのイベントハンドラ内部での例外はデバイスによってハンドリングされないため
                // ログは書き込みますが例外をデバイスにスローしません
                // Since the exception inside the event handler from a device is not handled by the device, 
                // although a log writes in, it does not throw the exception to a device. 
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
            }
            finally
            {
                ISessionContext sessionContext = sender as ISessionContext;
                sessionContext.UPOSEventHandlingOnGoing = false;
            }

        }

        public virtual SpeechSynthesisEvent PollForUPOSEvent(string ConsumerID)
        {
            try
            {
                ISessionContext sessionContext = base.GetSessionContext(ConsumerID);
                if (sessionContext.ConsumerEventPort != null)
                {
                    // 双方向通信でOpenSessionを呼び出した場合はPollForUPOSEventは使えません
                    // PollForUPOSEvent cannot be used when OpenSession is called by bi-directional communication. 
                    throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "bi-direction mode.", new FaultCode("Server"));
                }

                // このセッションで、既にPollForUPOSEventが呼ばれていた場合に前のPollForUPOSEventを終了して新たに待ち始めます。
                // これは、前のPollForUPOSEvent待ち時にネットワークが切断され、待ち時間内にアプリから再度PollForUPOSEventされたケースを想定しています。
                // これをしなくともセッションタイムアウトで解放されるので、最終的にリークはしませんが、アプリケーションにとって、
                // 既に(ネットワークの)エラーになった前のPollForUPOSEventが終わるまで新たにイベントがとれないというのは問題になります。
                // In this session, when PollForUPOSEvent is already called, front PollForUPOSEvent is ended and it newly begins to wait. 
                // A network is disconnected at the time of front PollForUPOSEvent waiting, and this assumes the case again PollForUPOSEvent from the application in waiting time. 
                // Since it is released by session timeout even if it does not carry out this, finally leak is not carried out, 
                // but it becomes a problem that an event cannot newly be taken until PollForUPOSEvent before already becoming an network) error finishes for application. 
                lock (sessionContext)
                {
                    if (sessionContext.IsPollingNow)
                    {
                        // 自分以外のスレッドがPollForUPOSEventしているなら前のスレッドに
                        // 終了するように通知する
                        // If threads other than themselves are PollForUPOSEvent(ing), 
                        // it will be reported that it ends to a front thread.
                        sessionContext.OtherPollForUPOSEventCalled.Signal();
                        // 前のスレッドの終了を待つ（すぐに待ち終わります）
                        // It waits for the end of a front thread (it finishes waiting immediately). 
                        sessionContext.PreviousPollForUPOSEventEnded.Wait(sessionContext.EventPollingTimeout);
                    }
                }
                sessionContext.IsPollingNow = true;

                IEventWait[] waits = new IEventWait[2];
                waits[0] = sessionContext.DeviceEventHappened;
                waits[1] = sessionContext.OtherPollForUPOSEventCalled;

                int signaledIndex = sessionContext.DeviceEventHappened.WaitForAny(waits, sessionContext.EventPollingTimeout);

                try
                {
                    if (signaledIndex != 0)
                    {
                        // タイムアウトまたは他のPollForUPOSEventによって待ちが中断
                        // Waiting is interrupted by timeout or other PollForUPOSEvent(s). 
                        base.LogWriteLineMessage(MethodBase.GetCurrentMethod(), "PollForUPOSEvent aborted by timeout or other PollForUPOSEvent call.");

                        return null;
                    }
                    if (sessionContext.DeviceEventArgs is Microsoft.PointOfService.DirectIOEventArgs)
                    {
                        Microsoft.PointOfService.DirectIOEventArgs e = sessionContext.DeviceEventArgs as Microsoft.PointOfService.DirectIOEventArgs;

                        SpeechSynthesisEvent posServiceEvent = new SpeechSynthesisEvent();
                        posServiceEvent.DirectIOEvent = new DirectIOEvent();

                        posServiceEvent.DirectIOEvent.Source = sessionContext.Device.ToString();
                        posServiceEvent.DirectIOEvent.EventID = e.EventId;
                        posServiceEvent.DirectIOEvent.TimeStamp = e.TimeStamp;
                        posServiceEvent.DirectIOEvent.EventNumber = e.EventNumber;
                        posServiceEvent.DirectIOEvent.Data = e.Data;
                        posServiceEvent.DirectIOEvent.Obj = base.ConvertStringToARTSBinary(sessionContext.IsLegacySO, sessionContext.CodePageConversion, (string)e.Object);;

                        return posServiceEvent;
                    }
                    else if (sessionContext.DeviceEventArgs is Microsoft.PointOfService.DataEventArgs)
                    {
                        Microsoft.PointOfService.DataEventArgs e = sessionContext.DeviceEventArgs as Microsoft.PointOfService.DataEventArgs;

                        SpeechSynthesisEvent posServiceEvent = new SpeechSynthesisEvent();
                        //posServiceEvent.DataEvent = new DataEvent();

                        //posServiceEvent.DataEvent.Source = sessionContext.Device.ToString();
                        //posServiceEvent.DataEvent.EventID = e.EventId;
                        //posServiceEvent.DataEvent.TimeStamp = e.TimeStamp;
                        //posServiceEvent.DataEvent.Status = e.Status;

                        return posServiceEvent;
                    }
                    else if (sessionContext.DeviceEventArgs is Microsoft.PointOfService.DeviceErrorEventArgs)
                    {
                        Microsoft.PointOfService.DeviceErrorEventArgs e = sessionContext.DeviceEventArgs as Microsoft.PointOfService.DeviceErrorEventArgs;

                        SpeechSynthesisEvent posServiceEvent = new SpeechSynthesisEvent();
                        posServiceEvent.ErrorEvent = new ErrorEvent();

                        posServiceEvent.ErrorEvent.Source = sessionContext.Device.ToString();
                        posServiceEvent.ErrorEvent.EventID = e.EventId;
                        posServiceEvent.ErrorEvent.TimeStamp = e.TimeStamp;
                        posServiceEvent.ErrorEvent.ErrorCode = (ErrorCode)EventConvert[e.ErrorCode];
                        posServiceEvent.ErrorEvent.ErrorCodeExtended = e.ErrorCodeExtended;
                        posServiceEvent.ErrorEvent.ErrorLocus = (ErrorLocus)EventConvert[e.ErrorLocus];
                        posServiceEvent.ErrorEvent.ErrorResponse = (ErrorResponse)EventConvert[e.ErrorResponse];

                        return posServiceEvent;
                    }
                    else if (sessionContext.DeviceEventArgs is Microsoft.PointOfService.OutputCompleteEventArgs)
                    {
                        Microsoft.PointOfService.OutputCompleteEventArgs e = sessionContext.DeviceEventArgs as Microsoft.PointOfService.OutputCompleteEventArgs;

                        SpeechSynthesisEvent posServiceEvent = new SpeechSynthesisEvent();
                        posServiceEvent.OutputCompleteEvent = new OutputCompleteEvent();

                        posServiceEvent.OutputCompleteEvent.Source = sessionContext.Device.ToString();
                        posServiceEvent.OutputCompleteEvent.EventID = e.EventId;
                        posServiceEvent.OutputCompleteEvent.TimeStamp = e.TimeStamp;
                        posServiceEvent.OutputCompleteEvent.OutputID = e.OutputId;

                        return posServiceEvent;
                    }
                    else if (sessionContext.DeviceEventArgs is Microsoft.PointOfService.StatusUpdateEventArgs)
                    {
                        Microsoft.PointOfService.StatusUpdateEventArgs e = sessionContext.DeviceEventArgs as Microsoft.PointOfService.StatusUpdateEventArgs;

                        SpeechSynthesisEvent posServiceEvent = new SpeechSynthesisEvent();
                        posServiceEvent.StatusUpdateEvent = new StatusUpdateEvent();

                        posServiceEvent.StatusUpdateEvent.Source = sessionContext.Device.ToString();
                        posServiceEvent.StatusUpdateEvent.EventID = e.EventId;
                        posServiceEvent.StatusUpdateEvent.TimeStamp = e.TimeStamp;
                        posServiceEvent.StatusUpdateEvent.Status = e.Status;

                        return posServiceEvent;
                    }
                    else
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_FAILURE }, "Invalid Device Event type.", new FaultCode("Server"));
                    }
                }
                finally
                {
                    sessionContext.IsPollingNow = false;
                    if (signaledIndex == 1)
                    {
                        sessionContext.PreviousPollForUPOSEventEnded.Signal();
                    }
                }
            }
            catch (Exception ex)
            {
                // 待ち合わせ中にセッションが閉じられると
                // WaitEventHandleハンドルがDisposeされるため
                // ObjectDisposedException例外がスローされます。
                // 例外処理そのものはException例外の処理と同じですが、
                // 待ち合わせ中のセッションタイムアウトの考慮をした記録として
                // コメントを残します
                // If a session is closed during waiting, 
                // since a WaitEventHandle handle is Dispose(d),
                // ObjectDisposedException exception is thrown. 
                // Although the exception handling itself is the same as processing of an Exception exception, 
                // leave this comment as a record of the session timed out while waiting for a consideration

                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }

        public virtual void SetEventResponse(string ConsumerID, SpeechSynthesisEventResponse Response)
        {
            try
            {
                ISessionContext sessionContext = base.GetSessionContext(ConsumerID);
                if (sessionContext.ConsumerEventPort != null)
                {
                    // 双方向通信でOpenSessionを呼び出した場合はSetEventResponseは使えません
                    // SetEventResponse cannot be used when OpenSession is called by bi-directional communication. 
                    throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "bi-direction mode.", new FaultCode("Server"));
                }

                if (Response.DirectIOEventResponse != null)
                {
                    var sessionContextArgs = sessionContext.DeviceEventArgs as Microsoft.PointOfService.DirectIOEventArgs;
                    if (sessionContextArgs == null)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid Operation.", new FaultCode("Server"));
                    }
                    if (Response.DirectIOEventResponse.EventID != sessionContextArgs.EventId)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid EventID.", new FaultCode("Server"));
                    }
                    sessionContext.DeviceEventResponse = Response.DirectIOEventResponse.DirectIOData;
                }
                //else if (Response.DataEventResponse != null)
                //{
                //    var sessionContextArgs = sessionContext.DeviceEventArgs as Microsoft.PointOfService.DataEventArgs;
                //    if (sessionContextArgs == null)
                //    {
                //        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid Operation.", new FaultCode("Server"));
                //    }
                //    if (Response.DataEventResponse.EventID != sessionContextArgs.EventId)
                //    {
                //        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid EventID.", new FaultCode("Server"));
                //    }
                //}
                else if (Response.ErrorEventResponse != null)
                {
                    var sessionContextArgs = sessionContext.DeviceEventArgs as Microsoft.PointOfService.DeviceErrorEventArgs;
                    if (sessionContextArgs == null)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid Operation.", new FaultCode("Server"));
                    }
                    if (Response.ErrorEventResponse.EventID != sessionContextArgs.EventId)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid EventID.", new FaultCode("Server"));
                    }
                    sessionContext.DeviceEventResponse = Response.ErrorEventResponse.ErrorResponse;
                }
                else if (Response.OutputCompleteEventResponse != null)
                {
                    var sessionContextArgs = sessionContext.DeviceEventArgs as Microsoft.PointOfService.OutputCompleteEventArgs;
                    if (sessionContextArgs == null)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid Operation.", new FaultCode("Server"));
                    }
                    if (Response.OutputCompleteEventResponse.EventID != sessionContextArgs.EventId)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid EventID.", new FaultCode("Server"));
                    }
                }
                else if (Response.StatusUpdateEventResponse != null)
                {
                    var sessionContextArgs = sessionContext.DeviceEventArgs as Microsoft.PointOfService.StatusUpdateEventArgs;
                    if (sessionContextArgs == null)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid Operation.", new FaultCode("Server"));
                    }
                    if (Response.StatusUpdateEventResponse.EventID != sessionContextArgs.EventId)
                    {
                        throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid EventID.", new FaultCode("Server"));
                    }
                }
                else
                {
                    throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid EventResponse argument.", new FaultCode("Server"));
                }

                // イベントレスポンスの設定が終わったのでデバイスのイベントハンドラを動かす
                // Since a setup of the event response finished, the event handler of a device is started. 
                sessionContext.SetEventResponseCalled.Signal();

            }
            catch (Exception ex)
            {
                base.LogWriteLineException(MethodBase.GetCurrentMethod(), ex);
                throw;
            }
        }


        #endregion

        #endregion

        #region IDisposable Member

        public override void Dispose()
        {
            base.Dispose();
        }

        #endregion

        /// <summary>
        /// セッションIDのチェック用メソッド
        /// チェックした結果、セッションIDが不正の場合は例外をスローする。
        /// セッションマネージャの内部やServiceBaseでの実装ではなく、
        /// ServiceBaseで抽象メソッドとして定義し、各デバイスサービスに実装させているのは、
        /// UposExceptionクラスがUPOS共通ではなく、各デバイスのネームスペースに所属しているため。
        /// 共通部分のコードでは、UposExceptionを書けない。
        /// A method to check SessionID.
        /// If the SessionID is incorrect, an exception is thrown. 
        /// Since a UposException class belongs to the name space of each device rather than common to UPOS, 
        /// this is defined as an abstract method in ServiceBase and implemented in each device service 
        /// instead of an implementation as a ServiceBase or inside of Session Manager.
        /// </summary>
        /// <param name="consumerID">Session ID</param>
        /// <param name="throwWhenExistId">true時は、すでにIDがセッションマネージャに登録されていたら例外をスローする。false時はIDがセッションマネージャに登録されていないならば例外をスローする |At the time of true, if ID is already registered into the session manager, this throws an exception. </param>
        protected override void ValidateSessionID(string consumerID, bool throwWhenExistId)
        {
            if (!base.IsValidSessionID(consumerID))
            {
                throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Invalid sessionID.", new FaultCode("Server"));
            }

            if (throwWhenExistId)
            {
                if (base.IsExistSession(consumerID))
                {
                    throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Duplicated sessionID.", new FaultCode("Server"));
                }
            }
            else
            {
                if (!base.IsExistSession(consumerID))
                {
                    throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_ILLEGAL }, "Not Active sessionID.", new FaultCode("Server"));
                }
            }
        }

        /// <summary>
        /// 指定されたセッションに関連されたリソースを解放します
        /// Releases the resources that are related to the specified session.
        /// </summary>
        /// <param name="sessionContext">セッションコンテキスト | Session context</param>
        protected override void CloseSessionResources(ISessionContext sessionContext)
        {
            DisposeDevice(sessionContext);
            base.CloseSessionBase(sessionContext, null, SessionContext_ServiceDirectIOEvent, SessionContext_ServiceErrorEvent, SessionContext_ServiceOutputCompleteEvent, SessionContext_ServiceStatusUpdateEvent);
        }

        /// <summary>
        /// 指定されたセッションに関連されたデバイスのインスタンスを破棄します。
        /// Destory the instance of the device associated with the specified session.
        /// </summary>
        /// <param name="sessionContext">セッションコンテキスト|Session Context</param>
        protected virtual void DisposeDevice(ISessionContext sessionContext)
        {
            if (sessionContext.Device == null)
            {
                // CloseDeviceの後にCloseDeviceを呼び出された場合、
                // すでにインスタンスは破棄されているので、なにもしない。
                // If called the CloseDevice after CloseDevice, 
                // Because instances are discarded already, nothing is done. 
                return;
            }

            var device = ConcretizationDevice(sessionContext.Device);

            if (device.State != Microsoft.PointOfService.ControlState.Closed)
            {
                device.FreezeEvents = true;
                base.WaitForEventHandlerReturned(sessionContext);

                device.Close();
                device.DirectIOEvent -= sessionContext.DeviceDirectIOEventHandler;
                device.ErrorEvent -= sessionContext.DeviceErrorEventHandler;
                device.OutputCompleteEvent -= sessionContext.DeviceOutputCompleteEventHandler;
                device.StatusUpdateEvent -= sessionContext.DeviceStatusUpdateEventHandler;
                //device.DataEvent -= sessionContext.DeviceDataEventHandler;
                sessionContext.Device = null;

                base.DeleteAsyncTemporaryFiles(sessionContext);
            }
        }

        /// <summary>
        /// デバイスを明示的にダウンキャストする
        /// このリファレンスを基に多数のデバイス（種類）をコーディングする際、
        /// デバイス種別へのダウンキャストコーディングの変更箇所を減らすためにこれを用いる
        /// 
        /// Downcast device explicitly.
        /// When coding on many devices (types) based on this reference, 
        /// the use of this in order to reduce the change in the downcast coding to the device type.
        /// </summary>
        /// <param name="device"></param>
        /// <returns></returns>
        protected virtual Microsoft.PointOfService.ToneIndicator ConcretizationDevice(Microsoft.PointOfService.PosDevice device)
        {
            if (device == null)
            {
                throw new FaultException<UposException>(new UposException() { ErrorCode = ErrorCode.E_CLOSED }, "Closed", new FaultCode("Server"));
            }

            return device as Microsoft.PointOfService.ToneIndicator;
        }

        /// <summary>
        /// クライアントへのイベントポートを明示的にダウンキャストする
        /// このリファレンスを基に多数のデバイス（種類）をコーディングする際、
        /// デバイス種別へのダウンキャストコーディングの変更箇所を減らすためにこれを用いる
        /// 
        /// Event port to the client to downcast explicitly.
        /// When coding on many devices (types) based on this reference, 
        /// the use of this in order to reduce the change in the downcast coding to the device type
        /// </summary>
        /// <param name="device"></param>
        /// <returns></returns>
        protected virtual UnifiedPOS.SpeechSynthesisEvents.V1_4.SpeechSynthesisEvent ConcretizationConsumerEventPort(object deviceEvent)
        {
            return deviceEvent as UnifiedPOS.SpeechSynthesisEvents.V1_4.SpeechSynthesisEvent;
        }
    }
}
