# coding: Shift_JIS
# coding: UTF-8

#
# Trust Design LLC : SECS/HSMS Communication library
#
# (c) Copyright Trust Design LLC.  2010-2024.  All rights reserved.
#


# ==============================================================================
#
# PythonIo : Test and sample program
#
#   Construct a message in AP and simply send and receive SECS messages.
#
#   (Note) In this sample, when making an HSMS connection, it is assumed that
#      The HOST side executes Passive connection and the EQUIP side executes
#      Active connection.
#
#
# Starting method
#
#   python PythonIo.py {h|e} [option [send_wait [send_sleep]]]
#   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#   h    : Refer to [HOST]  section of Sample.ini to determine operation
#   e    : Refer to [EQUIP] section of Sample.ini to determine operation
#
#   option  : Options for setting the details of operation (optional)
#	      Specify as a decimal number or as a hexadecimal number with 0x or
#	      x as a prefix.
#	      The details of the specified value for each bit are shown below.
#    F		 54 3210
#   +----+----+----+----+
#    |		 || |||+-- Function to use
#    |		 || |||    =0: _TDSCommXxxxx()		1:_TDSUDrvXxxx()
#    |		 || ||+--- SECS Header Byte order
#    |		 || ||	   =0: System order		1: Network order
#    |		 || |+---- Format for displaying messages in SECS list format
#    |		 || |	   =0: TDS Format		1: SML Format
#    |		 || +----- Whether to use MssgNextL() for SECS message display
#    |		 ||	   =0: Not use			1: Use
#    |		 |+------- Whether to use the SECS message definition file
#    |		 |	   =0: Not use			1: Use
#    |		 +-------- Whether to execute SECS message reception in a
#    |			   dedicated thread
#    |			   =0: No			1: Yes
#    +-------------------- Synchronize the connection status with communication
#			   control processing thread
#			   =0: No			1: Yes
#
#   send_wait   : Transmission interval when sending continuous messages (ms).
#   send_sleep  : Time to rest for a short time after sending a given number
#                 of times (SEND_NO) when sending continuous messages (ms).
#
#   Normally, "PythonIo h" and "PythonIo e" both operate on same machine or
#   different machines to communicate with each other. The communication partner
#   may be another sample AP such as BasicIo.exe or Callbackio.exe.
#
#   After startup, refer to the menu display, enter request code etc. and the
#   function is executed.
# 
#   When host starts up, it waits for a connection from equipment.
#   When device side is started, connection request and Select request are
#   automatically issued to host side.
#   On host side, repeat '1:Recv' processing, and confirm that display is
#   'STATUS=951: No data'. After that, exchange any message. On receiving side,
#   do not forget to reap received data until 'STATUS=951'.
#
#   The transaction ID used when sending secondary message uses that of primary
#   message received immediately before.
#
#   This sample omits some of abnormal processing.
#
#   "SECS_MODE" defined below is defined to determine whether or not connection
#   processing to Passive side in case of Active connection is performed when
#   using _TDSCommXxxx() as processing function.
#   (Note) Changing this value alone does not make TDS aware of the change in
#      SECS1 or HSMS.  TDS determines SECS1 or HSMS based on the setting of
#      SECSMODE in the configuration file (.ini).  To change this value, you
#      must change the setting of SECSMODE in .ini.
#
#   "FUNC_TYPE" is defined to select type of processing function to be used.
#   If you use _TDSUDrvXxxx(), there is no need to perform connection
#   processing for HSMS-SS Active connection, so there is no need to set
#   "SECS_MODE" in principle.
#   Since _TDSwitches SECS-1 connection or HSMS-SS connection in setting file
#   (.ini), user AP does not need to know connection method (SECS-1or HSMS and
#   Passive/Active at HSMS) as long as _TDSUDrvXxxx() is used as processing
#   function.
#
#   By changing values of "MSSG_USE_FILE" and "MSSG_DISP_TYPE" defined below,
#   you can change output format of SECS message displayed by this AP.
#   By changing value of "MSSG_USE_NEXTL", it is possible to change whether to
#   acquire field values as data or display list format when analyzing message
#   contents.
#   If "HEADER_BO" is set to 1, Byte Order of SECS message header obtained at
#   the time of Receive and Send can be obtained as the original network Byte
#   Order of the SECS message.
#   Similarly, when "USE_RECVTHREAD" is set to =1, a thread for performing
#   receiving process is activated, and display of received message and output
#   of the secondary message are automatically performed in the thread.
#   When using the receiving thread, keep in mind that prompt message may be
#   distorted.
#
#
# ==============================================================================
#
# PythonIo : テスト 及び サンプル・プログラム
#
#   ＡＰ内でメッセージを構築し、単純に SECS メッセージの送受信を行う。
#
#   (注) 本サンプルでは HSMS 接続する場合、HOST 側が Passive 接続、EQUIP 側が
#      Active 接続を実行すると仮定している。
#
#
# 起動方法
#
#   python PythonIo.py {h|e} [option [send_wait [send_sleep]]]
#   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#   h    : Sample.ini の [HOST]  セクションを参照し動作を決定する
#   e    : Sample.ini の [EQUIP]      :              :
#
#   option  : 動作の詳細を設定するオプション (省略可能)
#	      10進数 もしくは 接頭文字として 0x もしくは x を付与した 16進数
#	      で指定する。
#	      以下に指定値のビット毎の詳細を以下に示す。
#    F		 54 3210
#   +----+----+----+----+
#    |		 || |||+-- 使用する関数
#    |		 || |||    =0: _TDSCommXxxxx()		1:_TDSUDrvXxxx()
#    |		 || ||+--- SECS Header Byte order
#    |		 || ||	   =0: System order		1: Network order
#    |		 || |+---- SECS リスト形式でメッセージを表示する場合の形式
#    |		 || |	   =0: TDS 形式	         	1: SML 形式
#    |		 || +----- SECS メッセージ表示に MssgNextL() を使用するか否か
#    |		 ||	   =0: 使用しない		1: 使用する
#    |		 |+------- SECS メッセージ定義ファイル使用の有無
#    |		 |	   =0: 使用しない		1: 使用する
#    |		 +-------- SECS メッセージ受信を専用スレッドで実行するか否か
#    |			   =0: No			1: Yes
#    +-------------------- 接続状態を通信制御部に同期する
#			   =0: No			1: Yes
#
#   send_wait   : 連続メッセージ送信時の送信間隔 (ms)
#   send_sleep  : 連続メッセージ送信時に所定の回数 (SEND_NO) 送信した後に少し
#                 送信をお休みする時間 (ms)
#
#   通常、PythonIo h 及び PythonIo e の両方を、同一マシン、もしくは異なるマ
#   シン上で動作させて、相互通信を行う。通信相手は、BasicIo.exe、
#   Callbackio.exe 等、他のサンプルＡＰでもよい。
#
#   起動後、メニュ表示を参照し、要求コード等を入力し、機能を実行する。
# 
#   ホスト側は起動すると、装置側からの接続を待つ。装置側を起動すると、自動的
#   にホスト側に接続要求、Select 要求を発行する。ホスト側では、1:Recv 処理を
#   繰り返し行い、表示が「STATUS=951 : No data」となるのを確認する。その後、
#   任意のメッセージのやりとりを行う。受信側では、受信データの刈り取りを「
#   STATUS=951」になるまで行うことを忘れぬこと。
#
#   ２次メッセージを送信する際のトランザクションＩＤは、直前に受信した１次
#   メッセージのものを使用する。
#
#   本サンプルは、異常時処理を一部省略している。
#
#   以下で定義する "SECS_MODE" は、処理関数として _TDSCommXxxx() を使用する
#   場合で Active 接続の場合の Passive 側への接続処理の実行の有無を判断する
#   ために定義する。
#   (注) この値の変更だけで TDS が SECS1 or HSMS の変更を認識するわけではない。 
#      TDS は SECS1 or HSMS を判断するのは設定ファイル (.ini) の SECSMODE の
#      設定によるので、この値を変更する場合は .ini の SECSMODE の設定変更を
#      しなければならない。
#
#   "FUNC_TYPE" は、使用する処理関数の種別を選択するために定義する。
#   _TDSUDrvXxxx() を使用する場合は、HSMS-SS Active 接続の場合の接続処理を
#   行う必要がないので、本来であれば "SECS_MODE" の設定も必要がない。
#   TDS は、SECS-1 接続 or HSMS-SS 接続の切替は、設定ファイル (.ini) にて行う
#   ため、処理関数として _TDSUDrvXxxx() を使用する限りは、ユーザＡＰでは、
#   接続方式（SECS-1/HSMS-SS そして HSMS-SS時の Passive/Active）を知る必要は
#   ない。
#
#   以下で定義する "MSSG_USE_FILE"、"MSSG_DISP_TYPE" の値を変更すると、本ＡＰ
#   にて表示する SECS メッセージの出力形式を変更できる。
#   "MSSG_USE_NEXTL" の値を変更すると、メッセージ内容を解析する際に、項目値を
#   データとして取得するか、表示リスト形式で取得するかを変更できる。
#   "HEADER_BO" を 1 とすると、Receive、Send 時に取得する SECS メッセージ・
#   ヘッダのバイトオーダーを SECS メッセージ本来のネットワーク・バイトオーダー
#   として取得できる。
#   同様に "USE_RECVTHREAD" を =1 とすると、受信処理を行うスレッドを起動し、そ
#   のスレッド内で受信メッセージの表示、２次メッセージの出力を自動で行う。
#   受信スレッドを使用する場合、入力促進用メッセージに乱れが生じる事に留意
#   すること。
#
# ==============================================================================

import sys
import ctypes
import threading

from time   import *
from ctypes import *


class SHead(Structure):
  _fields_=     [("did"     ,c_ushort    )
                ,("scd"     ,c_ubyte     )
                ,("fcd"     ,c_ubyte     )
                ,("ptp"     ,c_ubyte     )
                ,("stp"     ,c_ubyte     )
                ,("sid"     ,c_ushort    )
                ,("xid"     ,c_ushort    )]

class SInfo(Structure):
  _fields_=     [("nox"     ,c_int       )
                ,("nort"    ,c_int       )
                ,("norf"    ,c_int       )
                ,("not3"    ,c_int       )
                ,("nof1"    ,c_int       )
                ,("nof3"    ,c_int       )
                ,("nof5"    ,c_int       )
                ,("nof7"    ,c_int       )
                ,("nof9"    ,c_int       )
                ,("nof11"   ,c_int       )
                ,("nof13"   ,c_int       )
                ,("dmy0"    ,c_int       )
                ,("trtst"   ,c_longlong  )
                ,("trtok"   ,c_longlong  )]


#tds=windll.LoadLibrary('TDS.dll')
tds=windll.LoadLibrary('./TDS.dll')
tds._TDSCommOpen         .restype=  c_int
tds._TDSCommOpen0        .restype=  c_int
tds._TDSCommClose        .restype=  c_int
tds._TDSCommRecv         .restype=  c_int
tds._TDSCommSend         .restype=  c_int
tds._TDSCommSendError    .restype=  c_int
tds._TDSCommSendComment  .restype=  c_int
tds._TDSCommStatus       .restype=  c_int
tds._TDSCommSelectStatus .restype=  c_int
tds._TDSCommHeaderBO     .restype=  c_int
tds._TDSCommSInfoClear   .restype=  c_int
tds._TDSCommSInfoGet     .restype=  c_int
tds._TDSCommSInfoOut     .restype=  c_int

tds._TDSErrorValue       .restype=  c_int
tds._TDSErrorPosition    .restype=  c_int
tds._TDSErrorStatus      .restype=  c_int
tds._TDSMssgErrorValue   .restype=  c_int
tds._TDSMssgErrorPosition.restype=  c_int
tds._TDSMssgErrorStatus  .restype=  c_int

tds._TDSMssgInit         .restype=  c_int
tds._TDSMssgEnd          .restype=  c_int
tds._TDSMssgBuild        .restype=  c_int
tds._TDSMssgBuildL       .restype=  c_int
tds._TDSMssgFind         .restype=  c_int
tds._TDSMssgExit         .restype=  c_int
tds._TDSMssgNext         .restype=  c_int
tds._TDSMssgNextL        .restype=  c_int

tds._TDSMDMssgInitialize .restype=  c_int
tds._TDSMDMssgTerminate  .restype=  c_int
tds._TDSMDMssgInit       .restype=  c_int
tds._TDSMDMssgEnd        .restype=  c_int
tds._TDSMDMssgBuild      .restype=  c_int
tds._TDSMDMssgFind       .restype=  c_int
tds._TDSMDMssgExit       .restype=  c_int
tds._TDSMDMssgNext       .restype=  c_int
tds._TDSMDMssgNextEx     .restype=  c_int
tds._TDSMDMssgNextL      .restype=  c_int
tds._TDSMDMssgAutoRes    .restype=  c_int

tds._TDSUDrvOpen         .restype=  c_int
tds._TDSUDrvClose        .restype=  c_int
tds._TDSUDrvRecv         .restype=  c_int
tds._TDSUDrvSend         .restype=  c_int
tds._TDSUDrvSendError    .restype=  c_int
tds._TDSUDrvSendComment  .restype=  c_int
tds._TDSUDrvStatus       .restype=  c_int
tds._TDSUDrvSelectStatus .restype=  c_int
tds._TDSUDrvHeaderBO     .restype=  c_int
tds._TDSUDrvSInfoClear   .restype=  c_int
tds._TDSUDrvSInfoGet     .restype=  c_int
tds._TDSUDrvSInfoOut     .restype=  c_int

tds._TDSCommOpen         .argtypes=[c_int,POINTER(c_char),POINTER(c_char),c_int,c_int,c_int,c_int,c_int,c_int]
tds._TDSCommOpen0        .argtypes=[c_int,POINTER(c_char),POINTER(c_char)]
tds._TDSCommClose        .argtypes=[c_int,c_int]
#tds._TDSCommRecv        .argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(SHead)]
#tds._TDSCommRecv        .argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
#tds._TDSCommSend        .argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(SHead)]
#tds._TDSCommSend        .argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
#tds._TDSCommSendError   .argtypes=[c_int,c_int,c_int,c_int,POINTER(SHead)  ,POINTER(SHead)  ,c_void_p]
#tds._TDSCommSendError   .argtypes=[c_int,c_int,c_int,c_int,POINTER(c_ubyte),POINTER(c_ubyte),c_void_p]
tds._TDSCommSendComment  .argtypes=[c_int,c_int,POINTER(c_char),POINTER(c_char),c_int]
tds._TDSCommStatus       .argtypes=[c_int,c_int]
tds._TDSCommSelectStatus .argtypes=[c_int,c_int,c_int]
#tds._TDSCommHeaderBO    .argtypes=[c_int,c_int,POINTER(SHead)]
#tds._TDSCommHeaderBO    .argtypes=[c_int,c_int,POINTER(c_ubyte)]
tds._TDSCommSInfoClear   .argtypes=[c_int,c_int]
#tds._TDSCommSInfoGet    .argtypes=[c_int,c_int,c_int,POINTER(SInfo)]
#tds._TDSCommSInfoGet    .argtypes=[c_int,c_int,c_int,POINTER(c_int)]
tds._TDSCommSInfoOut     .argtypes=[c_int,c_int]

tds._TDSErrorValue       .argtypes=[c_int]
tds._TDSErrorPosition    .argtypes=[c_int]
tds._TDSErrorStatus      .argtypes=[c_int,POINTER(c_int),POINTER(c_int)]
tds._TDSMssgErrorValue   .argtypes=[c_int]
tds._TDSMssgErrorPosition.argtypes=[c_int]
tds._TDSMssgErrorStatus  .argtypes=[c_int,POINTER(c_int),POINTER(c_int)]

tds._TDSMssgInit         .argtypes=[c_int,POINTER(c_ubyte),c_int,c_int]
tds._TDSMssgEnd          .argtypes=[c_int,c_int,POINTER(c_ubyte)]
tds._TDSMssgBuild        .argtypes=[c_int,c_int,POINTER(c_ubyte),c_int,c_int,c_void_p]
tds._TDSMssgBuildL       .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_char)]
#tds._TDSMssgFind        .argtypes=[c_int,POINTER(c_ubyte),c_int,c_int,POINTER(SHead)  ,POINTER(c_char)]
#tds._TDSMssgFind        .argtypes=[c_int,POINTER(c_ubyte),c_int,c_int,POINTER(c_ubyte),POINTER(c_char)]
tds._TDSMssgExit         .argtypes=[c_int,c_int,POINTER(c_ubyte)]
tds._TDSMssgNext         .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_int),POINTER(c_int),POINTER(c_int),c_void_p,c_int]
tds._TDSMssgNextL        .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_int),POINTER(c_int),POINTER(c_char),c_int]

tds._TDSMDMssgInitialize .argtypes=[c_int,c_int,POINTER(c_char)]
tds._TDSMDMssgTerminate  .argtypes=[c_int,c_int]
tds._TDSMDMssgInit       .argtypes=[c_int,c_int,POINTER(c_ubyte),c_int,POINTER(c_char)]
tds._TDSMDMssgEnd        .argtypes=[c_int,c_int,POINTER(c_ubyte)]
tds._TDSMDMssgBuild      .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_char),c_int,c_void_p]
tds._TDSMDMssgFind       .argtypes=[c_int,c_int,POINTER(c_ubyte),c_int,c_int,POINTER(c_char)]
tds._TDSMDMssgExit       .argtypes=[c_int,c_int,POINTER(c_ubyte)]
tds._TDSMDMssgNext       .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_char),c_int,c_void_p]
tds._TDSMDMssgNextEx     .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_char),c_int,c_void_p,POINTER(c_int),POINTER(c_int)]
tds._TDSMDMssgNextL      .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_int),POINTER(c_int),POINTER(c_char),c_int]
#tds._TDSMDMssgAutoRes   .argtypes=[c_int,c_int,POINTER(SHead)  ,POINTER(c_ubyte),c_int,c_int,POINTER(c_char),POINTER(c_char),POINTER(c_int)]
#tds._TDSMDMssgAutoRes   .argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_ubyte),c_int,c_int,POINTER(c_char),POINTER(c_char),POINTER(c_int)]

tds._TDSUDrvOpen         .argtypes=[c_int,POINTER(c_char),POINTER(c_char),c_int]
tds._TDSUDrvClose        .argtypes=[c_int,c_int]
#tds._TDSUDrvRecv        .argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(SHead)]
#tds._TDSUDrvRecv        .argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
#tds._TDSUDrvSend        .argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(SHead)]
#tds._TDSUDrvSend        .argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
#tds._TDSUDrvSendError   .argtypes=[c_int,c_int,c_int,c_int,POINTER(SHead)  ,POINTER(SHead)  ,c_void_p]
#tds._TDSUDrvSendError   .argtypes=[c_int,c_int,c_int,c_int,POINTER(c_ubyte),POINTER(c_ubyte),c_void_p]
tds._TDSUDrvSendComment  .argtypes=[c_int,c_int,POINTER(c_char),POINTER(c_char),c_int]
tds._TDSUDrvStatus       .argtypes=[c_int,c_int]
tds._TDSUDrvSelectStatus .argtypes=[c_int,c_int,c_int]
#tds._TDSUDrvHeaderBO    .argtypes=[c_int,c_int,POINTER(SHead)]
#tds._TDSUDrvHeaderBO    .argtypes=[c_int,c_int,POINTER(c_ubyte)]
tds._TDSUDrvSInfoClear   .argtypes=[c_int,c_int]
#tds._TDSUDrvSInfoGet    .argtypes=[c_int,c_int,c_int,POINTER(SInfo)]
#tds._TDSUDrvSInfoGet    .argtypes=[c_int,c_int,c_int,POINTER(c_int)]
tds._TDSUDrvSInfoOut     .argtypes=[c_int,c_int]


# ------------------------------------------------------------------------------

E_BADF          =9
E_BUSY          =16
E_NOMEM         =12
E_NODEV         =19
E_2BIG          =7

E_NOTCONNECT    =999
E_DESELECT      =998
E_REJECT        =997
E_SEPARATE      =996
E_SELECT        =992
E_CONNECT       =991
E_RETRYOVER     =989
E_T8TIMEDOUT    =988
E_T7TIMEDOUT    =987
E_T6TIMEDOUT    =986
E_T5TIMEDOUT    =985
E_T4TIMEDOUT    =984
E_T3TIMEDOUT    =983
E_T2TIMEDOUT    =982
E_T1TIMEDOUT    =981
E_ILLBLOCK      =980
E_NODATA        =951


# ------------------------------------------------------------------------------

SECS_MODE       =1              # SECS/HSMS mode
                                # 0    : SECS-1
                                # 1    : HSMS
                                # (Note) See comments above
                                # (注) 上部コメント参照
UDRV_MASK       =0x8383ffff     # Mask value of UDrvOpen()
                                # 0          : Set =0x49
                                # 0x8383ffff : All event

FUNC_TYPE       =1              # Type of function used
                                # 通信に使用する関数の種別
                                # 0    : _TDSCommXxxxx
                                # 1    : _TDSUDrvXxxxx
HEADER_BO       =0              # Header byte order
                                # 取得するヘッダの Byte Order
                                # 0    : System  Order
                                # 1    : Network Order
MSSG_DISP_TYPE  =0x20           # SECS Message display format
                                # 0x00 : TDS Format
                                # 0x20 : SML Format
MSSG_USE_NEXTL  =1              # Use MssgNextL() or not
                                # 0    : Not use
                                # 1    : Use

MSSG_USE_FILE   =0x00           # Message definition file
                                # 0x00 : Not use
                                # 0x80 : Use to display item names
                                #        使用して項目名表示する
USE_RECVTHREAD  =1              # Use of Callback function
                                # 0    : Not use
                                # 1    : Use

SYNC_STATUS     =1              # Synchronize connection status
                                # 接続状態の同期
                                # 0    : No
                                # 1    : Yes

SEND_WAIT       =200            # Message sending interval              (ms)
SEND_NO         =10             # #of times until message transmission break
SEND_SLEEP      =1000           # Waiting time                          (ms)
ERROR_SLEEP     =2000           # Waiting time when an  error occurs    (ms)

PARAMFILE       =b"Sample.ini"


# ------------------------------------------------------------------------------

FuncType        =FUNC_TYPE      # sys.argv[2]&0x0001
HeaderBO        =HEADER_BO      # sys.argv[2]&0x0002
MssgDispType    =MSSG_DISP_TYPE # sys.argv[2]&0x0004
MssgUseNextL    =MSSG_USE_NEXTL # sys.argv[2]&0x0008
MssgUseFile     =MSSG_USE_FILE  # sys.argv[2]&0x0010
UseRecvThrd     =USE_RECVTHREAD # sys.argv[2]&0x0020
SyncStatus      =SYNC_STATUS    # sys.argv[2]&0x8000

SendWait        =SEND_WAIT      # sys.argv[3]
SendSleep       =SEND_SLEEP     # sys.argv[4]

Fd              =0              # Communication identifier
Md              =0              # Message analysis identifier
OType           =0              # Operation type  (0:Host  1:Equipment)
Break           =0              # End instruction to thread
                                # スレッド終了指示

cnt249          =0
cnt250          =0
cnt611          =0

Cs1             =threading.Lock()


# ==============================================================================
# Common function ==============================================================


# ------------------------------------------------------------------------------
# Display SECS messages on standard output -------------------------------------
# SECS メッセージを標準出力に表示する。 ----------------------------------------

def DispSECSMssg(tp,hd,did,sf,xid,msg,ln):
#   int         tp              # i  : Message type
#                               #       =0 : Transmission result
#                               #        1 : Received message
#                               #        2 : Send message
#   SHead       hd              # i  : SECS Message Header
#   int         did             # i  : SECS Message Device ID
#   int         sf              # i  : SECS Message SF-Code
#   int         xid             # i  : SECS Message Transaction ID
#   c_ubyte     msg[]           # i  : SECS Message Message strage area
#                               #           (Header not included)
#   int         ln)             # i  : SECS Message byte length

  global    Fd,Md

  ctp   =["SRES","RECV","SEND"]

  pass;                                 p_msg=cast(msg ,POINTER(c_ubyte))
  mnm =create_string_buffer(  32);      p_mnm=cast(mnm ,POINTER(c_char))
  strg=create_string_buffer(2048);      p_str=cast(strg,POINTER(c_char))
  item=(c_ubyte*2048)();                p_itm=cast(item,POINTER(c_ubyte))
  pass;                                 itmst=cast(item,c_char_p)
  itmsb=cast(item,POINTER(c_byte));     itmub=cast(item,POINTER(c_ubyte))
  itmss=cast(item,POINTER(c_short));    itmus=cast(item,POINTER(c_ushort))
  itmsi=cast(item,POINTER(c_int));      itmui=cast(item,POINTER(c_uint))
  itmsl=cast(item,POINTER(c_int64));    itmul=cast(item,POINTER(c_uint64))
  itmfl=cast(item,POINTER(c_float));    itmdb=cast(item,POINTER(c_double))
  cform=c_int(0)
  csz  =c_int(0)
  cnoi =c_int(0)

  md  =0;       dp  =MssgUseFile|MssgDispType
  rbit=" ";     wbit=" "
  if (did&0x8000)!=0:   rbit="R"
  if (sf &0x8000)!=0:   wbit="W"
  if  did        < 0:   sdid=  "{0:6d}" .format(did)
  else:                 sdid="0x{0:04x}".format(did)
  sfcode="S{0:d}F{1:d}".format(int((sf&0x7f00)/0x0100),int(sf&0xff))

  if type(hd) is SHead:
    form="[{0:s}]  Dev={1:6s}  {2:8s}  {3:s}{4:s} XId=0x{5:04x}.{6:04x}  Len={7:3d}" \
        +"  Head:did=0x{8:04x} sf=0x{9:02x}{10:02x} ptp=0x{11:02x},{12:02x}" \
        +" txid=0x{13:04x},{14:04x}"
    print(form.format(ctp[tp],sdid,sfcode,rbit,wbit,(xid>>16)&0xffff,xid&0xffff,ln \
                    ,hd.did,hd.scd,hd.fcd,hd.ptp,hd.stp,hd.sid,hd.xid))
  else:
    hv=cast(hd   ,POINTER(c_ubyte));    p_hd =cast(hd  ,POINTER(c_ubyte))
    form="[{0:s}]  Dev={1:6s}  {2:8s}  {3:s}{4:s} XId=0x{5:04x}.{6:04x}  Len={7:3d}" \
        +"  Head=0x{8:02x},{9:02x},{10:02x},{11:02x},{12:02x},{13:02x}" \
        +",{14:02x},{15:02x},{16:02x},{17:02x}"
    print(form.format(ctp[tp],sdid,sfcode,rbit,wbit,(xid>>16)&0xffff,xid&0xffff,ln \
                    ,hv[0],hv[1],hv[2],hv[3],hv[4],hv[5],hv[6],hv[7],hv[8],hv[9]))

  if (MssgUseFile&0x80)!=0:     fm =0x8000      # Use message definition file
  else:                         fm =0x0000      # Not use

  if ln>0:
    if tp==1:   dp|=0x3000;     fm|=0x3000      # In case of reception
    else:       dp|=0x2000;     fm|=0x2000      # In case of sending

    md=TDSFind(fm,msg,ln,hd,mnm)
    if md > 0:
      mname=mnm.value.decode()
      if len(mname)>0:  print(mname)            # Message name

      la=0
      while True:
        if MssgUseNextL==0:     # Get item value
          rtn=tds._TDSMssgNext(md \
            ,0,p_msg,byref(cform),byref(csz),byref(cnoi),p_itm,2048)
          form=cform.value&0o077; noi=cnoi.value; sz=csz.value
          if rtn< 0:            break
          print("{0:03o}:{1:d}*{2:3d}:".format(form,sz,noi),end="")
                                # Display of field value
                                # The third and subsequent numbers are omitted
                                # 数値の３番目以降は省略
          if   form==0o000: print("L [{0:2d}]"                  .format(noi))
          elif form==0o010: print("B [{0:2d}]=0x{1:02x},{2:02x}".format(noi,itmub[0],itmub[1]))
          elif form==0o011: print("T [{0:2d}]={1:d},{2:d}"      .format(noi,itmub[0],itmub[1]))
          elif form==0o020: print("A [{0:2d}]={1:s}"            .format(noi,itmst.value.decode("Shift_JIS")))
          elif form==0o021: print("J [{0:2d}]={1:s}"            .format(noi,itmst.value.decode("Shift_JIS")))
          elif form==0o022: print("K [{0:2d}]={1:s}"            .format(noi,itmst.value.decode("Shift_JIS")))
          elif form==0o030: print("I8[{0:2d}]={1:d},{2:d}"      .format(noi,itmsl[0],itmsl[1]))
          elif form==0o031: print("I1[{0:2d}]={1:d},{2:d}"      .format(noi,itmsb[0],itmsb[1]))
          elif form==0o032: print("I2[{0:2d}]={1:d},{2:d}"      .format(noi,itmss[0],itmss[1]))
          elif form==0o034: print("I4[{0:2d}]={1:d},{2:d}"      .format(noi,itmsi[0],itmsi[1]))
          elif form==0o040: print("F8[{0:2d}]={1:e},{2:e}"      .format(noi,itmdb[0],itmdb[1]))
          elif form==0o044: print("F4[{0:2d}]={1:e},{2:e}"      .format(noi,itmfl[0],itmfl[1]))
          elif form==0o050: print("U8[{0:2d}]={1:d},{2:d}"      .format(noi,itmul[0],itmul[1]))
          elif form==0o051: print("U1[{0:2d}]={1:d},{2:d}"      .format(noi,itmub[0],itmub[1]))
          elif form==0o052: print("U2[{0:2d}]={1:d},{2:d}"      .format(noi,itmus[0],itmus[1]))
          elif form==0o054: print("U4[{0:2d}]={1:d},{2:d}"      .format(noi,itmui[0],itmui[1]))
          else:             print("")

        else:                                   # Get in list format
                                                # リスト表示形式で取得
          rtn=tds._TDSMssgNextL(md,dp,p_msg,byref(cform),byref(cnoi),strg,2048)
          form=cform.value&0o077; noi=cnoi.value
          if  rtn       < 0:    break
          if (dp&0x70)  > 0x10:                 # Incase of SML
            i=la
            while i>rtn:
              j=0
              while j<(i*2):
                print(" ",end="")
                j+=1
              print(">")                        # Display '>'
              i-=1
          la=rtn                                # Save current hierarchy
                                                # 現在の階層を保存
          print("  {0:s}".format(strg.value.decode("Shift_JIS")))
                                                # Display acquired field value
                                                # 取得した項目値を表示
          if (dp&0x70)>0x10 and form==000 and noi==0:
            j=0
            while j<((la+1)*2):
              print(" ",end="")
              j+=1
            print(">")                          # Display '>'

      if MssgUseNextL!=0:
        if (dp&0x70)   > 0x10:
          i=la
          while i>0:
            j=0
            while j<(i*2):
              print(" ",end="")
              j+=1
            print(">")                          # Show remaining '>'
            i-=1                                # 残りの '>' 表示

      tds._TDSMssgExit(md,0,p_msg)


    if (MssgUseFile&0x80)!=0  and  MssgUseNextL==0:
                # Refer to the comment in corresponding section of SubFuncsion.h
                # SubFuncsion.h の該当箇所のコメントを参照すること
      sf&=0x7fff
      rtn=tds._TDSMDMssgFind(Md,0,p_msg,ln,sf,mnm)
      if rtn>0:
        mname=mnm.value.decode()
        print("Message Definition Name = '{0:s}'".format(mname))

        if   sf ==0x0115:                       # S1F21
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"VB"   , 0,p_itm)
          if no0>=0:
            print("VB          [{0:2d}]=0x"     .format(no0)     ,end="")
            i=0
            while i<no0:
              print("{0:02x} "                  .format(itmub[i]),end=""); i+=1
            print("")
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"MDLN" , 0,p_itm)
          if no0>=0:
            print("MDLN        [{0:2d}]='{1:s}'".format(no0,itmst.value.decode()))
         #no0=tds._TDSMDMssgNext(Md,0,p_msg,b"SOFTREV",0,p_itm)
         #if no0>=0:                            # Not support JIS-8 chara.
         #  print("SOFTREV     [{0:2d}]='{1:s}'".format(no0,itmst.value.decode()))
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"VI4"  , 0,p_itm)
          if no0>=0:
            print("VI4         [{0:2d}]="       .format(no0)     ,end="")
            i=0
            while i<no0:
              print("{0:d} "                    .format(itmsi[i]),end=""); i+=1
            print("")
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"VF4"  , 0,p_itm)
          if no0>=0:
            print("VF4         [{0:2d}]="       .format(no0)     ,end="")
            i=0
            while i<no0:
              print("{0:e} "                    .format(itmfl[i]),end=""); i+=1
            print("")

        elif sf ==0x0116:                       # S1F22
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"VT"   , 0,p_itm)
          if no0>=0:
            print("VT          [{0:2d}]=0x"     .format(no0)     ,end="")
            i=0
            while i<no0:
              print("{0:02x} "                  .format(itmub[i]),end=""); i+=1
            print("")
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"COMMENT",0,p_itm)
          if no0>=0:
            print("COMMENT     [{0:2d}]='{1:s}'".format(no0,itmst.value.decode("Shift_JIS")))
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"AU8"  , 0,p_itm)
          if no0>=0:
            print("AU8         [{0:2d}]="       .format(no0)     ,end="")
            i=0
            while i<no0:
              print("{0:d} "                    .format(itmul[i]),end=""); i+=1
            print("")
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"VF8"  , 0,p_itm)
          if no0>=0:
            print("VF8         [{0:2d}]="       .format(no0)     ,end="")
            i=0
            while i<no0:
              print("{0:e} "                    .format(itmdb[i]),end=""); i+=1
            print("")

        elif sf ==0x0231:                       # S2F49
          if tds._TDSMDMssgNext (Md,0,p_msg,b"NOI1" , 0,p_itm) > 0:
            no1=itmsi[0]
            print("NOI1        [{0:2d}]"        .format(no1))
            i=0
            while i<no1:
              iname="NOI2:{0:d}".format(i+1);
              inm  =iname.encode();
                # Refer to the comment in corresponding section of SubFuncsion.h
                # SubFuncsion.h の該当箇所のコメントを参照すること
              if tds._TDSMDMssgNext(Md,0,p_msg,inm,0,p_itm) > 0:
                no2=itmsi[0]
                print("{0:12s}[{1:2d}]"         .format(iname,no2))
                j=0
                while j<no2:
                  iname="WAFERID:{0:d}:{1:d}"   .format(i+1,j+1);  
                  inm  =iname.encode();                                    j+=1
                  no0  =tds._TDSMDMssgNext(Md,0,p_msg,inm,0,p_itm)
                  if no0>=0:
                    print("{0:12s}[{1:2d}]='{2:s}'".format(iname,no0,itmst.value.decode()))
              i+=1

        elif sf ==0x060b:                       # S6F11
          no0=tds._TDSMDMssgNext(Md,0,p_msg,b"DATAID",0,p_itm)
          if no0>=0:
            print("DATAIDB     [{0:2d}]="       .format(no0)     ,end="")
            i=0
            while i<no0:
              print("{0:d} "                    .format(itmsi[i]),end=""); i+=1
            print("")

        tds._TDSMDMssgExit(Md,0,p_msg)




# ------------------------------------------------------------------------------
# Display sent and received data -----------------------------------------------

def DispData(tp,hd,did,sf,xid,msg,ln,rtn):
#   int         tp              # i  : Message type
#                               #       =0 : Transmission result
#                               #        1 : Received message
#                               #        2 : Send message
#   SHead       hd              # i  : SECS Message Header
#   int         did             # i  : SECS Message Device ID
#   int         sf              # i  : SECS Message SF-Code
#   int         xid             # i  : SECS Message Transaction ID
#   c_ubyte     msg[]           # i  : SECS Message Body
#   int         ln              # i  : Byte length of 'msg'
#   int         rtn             # i  : I/O return value

  global    Fd,Md
  global    Cs1

  Cs1.acquire()
  ok=0
  if rtn<0:
    ok=1
    if (rtn<(-E_NOTCONNECT) or (-E_ILLBLOCK)<rtn) and rtn!=(-E_NODATA):
      print("ERROR  [{0:d}]".format(rtn),end="")
      if   rtn==(-E_NODEV):
        print(" : No such device ID");      ln=ok=0
      elif rtn==(-E_2BIG ):
        print(" : Data size to large");     ln=ok=0
      else:                     print("")

    else:
      stat=TDSStatus(0)
      print("STATUS = {0:d},{1:d} : ".format(-rtn,stat),end="")
      if   rtn==-E_NODATA:      print("No data")
      elif rtn==-E_ILLBLOCK:    print("Illegal block#")
      elif rtn==-E_T1TIMEDOUT:  print("T1 Timeout occur")
      elif rtn==-E_T2TIMEDOUT:  print("T2 Timeout occur")
      elif rtn==-E_T3TIMEDOUT:  print("T3 Timeout occur")
      elif rtn==-E_T4TIMEDOUT:  print("T4 Timeout occur")
      elif rtn==-E_T5TIMEDOUT:  print("T5 Timeout occur")
      elif rtn==-E_T6TIMEDOUT:  print("T6 Timeout occur")
      elif rtn==-E_T7TIMEDOUT:  print("T7 Timeout occur")
      elif rtn==-E_T8TIMEDOUT:  print("T8 Timeout occur")
      elif rtn==-E_RETRYOVER:   print("Retry over")
      elif rtn==-E_CONNECT:     print("Connected")
      elif rtn==-E_SELECT:      print("Selected   ({0:04x})".format(did))
      elif rtn==-E_REJECT:      print("Rejected XId={0:04x}".format(xid))
      elif rtn==-E_DESELECT:    print("Deselected ({0:04x})".format(did))
      elif rtn==-E_SEPARATE:    print("Separated  ({0:04x})".format(did))
      elif rtn==-E_NOTCONNECT:  print("Not connected")
      else:                     print("")

  if ok==0:     DispSECSMssg(tp,hd,did,sf,xid,msg,ln)
  Cs1.release()



# ==============================================================================
# SECS Wrapper functions -------------------------------------------------------

def TDSOpen(mode,sect):

  if FuncType==0: rtn=tds._TDSCommOpen(mode,PARAMFILE,sect,0,0,0,0,0,0)
  else:           rtn=tds._TDSUDrvOpen(mode,PARAMFILE,sect,UDRV_MASK)

  return rtn



def TDSClose(mode):
  global    Fd

  if FuncType==0: rtn=tds._TDSCommClose(Fd,0)
  else:           rtn=tds._TDSUDrvClose(Fd,0)

  return rtn



def TDSRecv(mode,did,sf,xid,msg,ln,hd):
  global    Fd
  p_msg=cast(msg,POINTER(c_ubyte))

  if mode      < 0:
    cmd=0x0000
  # if HeaderBO!=0: cmd=0x2000
  # else:           cmd=0x0000
  else:             cmd=mode

  if type(hd) is SHead:
    if FuncType==0:
      tds    ._TDSCommRecv.argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(SHead)]
      rtn=tds._TDSCommRecv(Fd,cmd,byref(did),byref(sf),byref(xid),p_msg,ln,byref(hd))
    else:
      tds    ._TDSUDrvRecv.argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(SHead)]
      rtn=tds._TDSUDrvRecv(Fd,cmd,byref(did),byref(sf),byref(xid),p_msg,ln,byref(hd))
  else:
    p_hd =cast(hd ,POINTER(c_ubyte))
    if FuncType==0:
      tds    ._TDSCommRecv.argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
      rtn=tds._TDSCommRecv(Fd,cmd,byref(did),byref(sf),byref(xid),p_msg,ln,p_hd)
    else:
      tds    ._TDSUDrvRecv.argtypes=[c_int,c_int,POINTER(c_int),POINTER(c_int),POINTER(c_int),POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
      rtn=tds._TDSUDrvRecv(Fd,cmd,byref(did),byref(sf),byref(xid),p_msg,ln,p_hd)

  if HeaderBO!=0: # The mode setting of CommRecv() is sufficient, but
                  # for testing purposes, CommHeaderBO() is used here.
                  # CommRecv() の mode 設定でことは足りるが、ここでは
                  # 試験のため、敢えて CommHeaderBO() を使用する。
    if type(hd) is SHead:
      if FuncType==0:
        tds._TDSCommHeaderBO.argtypes=[c_int,c_int,POINTER(SHead)]
        tds._TDSCommHeaderBO(Fd,0,byref(hd))
      else:
        tds._TDSUDrvHeaderBO.argtypes=[c_int,c_int,POINTER(SHead)]
        tds._TDSUDrvHeaderBO(Fd,0,byref(hd))
    else:
      p_hd =cast(hd ,POINTER(c_ubyte))
      if FuncType==0:
        tds._TDSCommHeaderBO.argtypes=[c_int,c_int,POINTER(c_ubyte)]
        tds._TDSCommHeaderBO(Fd,0,p_hd)
      else:
        tds._TDSUDrvHeaderBO.argtypes=[c_int,c_int,POINTER(c_ubyte)]
        tds._TDSUDrvHeaderBO(Fd,0,p_hd)

  return rtn



def TDSSend(mode,did,sf,xid,msg,ln,hd):
  global    Fd
  p_msg=cast(msg,POINTER(c_ubyte))

  if mode      < 0:
    if HeaderBO!=0: cmd=0x2000
    else:           cmd=0x0000
  else:             cmd=mode

  if type(hd) is SHead:
    if FuncType==0:
      tds    ._TDSCommSend.argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(SHead)]
      rtn=tds._TDSCommSend(Fd,cmd,did,sf,xid,p_msg,ln,byref(hd))
    else:
      tds    ._TDSUDrvSend.argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(SHead)]
      rtn=tds._TDSUDrvSend(Fd,cmd,did,sf,xid,p_msg,ln,byref(hd))

  else:
    p_hd =cast(hd ,POINTER(c_ubyte))
    if FuncType==0:
      tds    ._TDSCommSend.argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
      rtn=tds._TDSCommSend(Fd,cmd,did,sf,xid,p_msg,ln,p_hd)
    else:
      tds    ._TDSUDrvSend.argtypes=[c_int,c_int,c_int,c_int,c_int,POINTER(c_ubyte),c_int,POINTER(c_ubyte)]
      rtn=tds._TDSUDrvSend(Fd,cmd,did,sf,xid,p_msg,ln,p_hd)

  return rtn



def TDSStatus(mode):
  global    Fd

  if FuncType==0:   stat=tds._TDSCommStatus(Fd,mode)
  else:             stat=tds._TDSUDrvStatus(Fd,mode)

  return stat



def TDSFind(mode,msg,ln,hd,mnm):
  global    Fd
  p_msg=cast(msg ,POINTER(c_ubyte))
  p_mnm=cast(mnm ,POINTER(c_char))

  if type(hd) is SHead:
    tds   ._TDSMssgFind.argtypes=[c_int,POINTER(c_ubyte),c_int,c_int,POINTER(SHead)  ,POINTER(c_char)]
    md=tds._TDSMssgFind(mode,p_msg,ln,Fd,byref(hd),p_mnm)
  else:
    p_hd =cast(hd ,POINTER(c_ubyte))
    tds   ._TDSMssgFind.argtypes=[c_int,POINTER(c_ubyte),c_int,c_int,POINTER(c_ubyte),POINTER(c_char)]
    md=tds._TDSMssgFind(mode,p_msg,ln,Fd,p_hd     ,p_mnm)

  return md



def TDSAutoRes(mode,hd,msg,rtn,ln,rnm,snm,sf):
  global    Md
  p_msg=cast(msg ,POINTER(c_ubyte))
  p_rnm=cast(rnm ,POINTER(c_char))
  p_snm=cast(snm ,POINTER(c_char))

  if type(hd) is SHead:
    tds   ._TDSMDMssgAutoRes.argtypes=[c_int,c_int,POINTER(SHead)  ,POINTER(c_ubyte),c_int,c_int,POINTER(c_char),POINTER(c_char),POINTER(c_int)]
    ln=tds._TDSMDMssgAutoRes(Md,mode,hd  ,p_msg,rtn,ln,p_rnm,p_snm,byref(sf))
  else:
    p_hd =cast(hd ,POINTER(c_ubyte))
    tds   ._TDSMDMssgAutoRes.argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_ubyte),c_int,c_int,POINTER(c_char),POINTER(c_char),POINTER(c_int)]
    ln=tds._TDSMDMssgAutoRes(Md,mode,p_hd,p_msg,rtn,ln,p_rnm,p_snm,byref(sf))

  return ln



def TDSHeaderBO(mode,hd):
  global    Fd

  if type(hd) is SHead:
    if FuncType==0:
      tds    ._TDSCommHeaderBO.argtypes=[c_int,POINTER(SHead)]
      rtn=tds._TDSCommHeaderBO(Fd,mode,byref(hd))
    else:
      tds    ._TDSUDrvHeaderBO.argtypes=[c_int,POINTER(SHead)]
      rtn=tds._TDSUDrvHeaderBO(Fd,mode,byref(hd))
  else:
    p_hd =cast(hd ,POINTER(c_ubyte))
    if FuncType==0:
      tds    ._TDSCommHeaderBO.argtypes=[c_int,POINTER(c_ubyte)]
      rtn=tds._TDSCommHeaderBO(Fd,mode,p_hd)
    else:
      tds    ._TDSUDrvHeaderBO.argtypes=[c_int,POINTER(c_ubyte)]
      rtn=tds._TDSUDrvHeaderBO(Fd,mode,p_hd)

  return 0



def TDSSInfoGet(mode,sf,hd):
  global    Fd

  if type(hd) is SInfo:
    if FuncType==0:
      tds    ._TDSCommSInfoGet.argtypes=[c_int,c_int,c_int,POINTER(SInfo)]
      rtn=tds._TDSCommSInfoGet(Fd,mode,sf,byref(hd))
    else:
      tds    ._TDSUDrvSInfoGet.argtypes=[c_int,c_int,c_int,POINTER(SInfo)]
      rtn=tds._TDSUDrvSInfoGet(Fd,mode,sf,byref(hd))
  else:
    p_hd =cast(hd ,POINTER(c_uint))
    if FuncType==0:
      tds    ._TDSCommSInfoGet.argtypes=[c_int,c_int,c_int,POINTER(c_uint)]
      rtn=tds._TDSCommSInfoGet(Fd,mode,sf,p_hd)
    else:
      tds    ._TDSUDrvSInfoGet.argtypes=[c_int,c_int,c_int,POINTER(c_uint)]
      rtn=tds._TDSUDrvSInfoGet(Fd,mode,sf,p_hd)

  return rtn



# ==============================================================================
# S1F1 message construction and sending ----------------------------------------

def SendS1F1():
  global    Md
  hd =SHead()
# hd =(c_ubyte*12)()
  msg=(c_ubyte*16)();
  sf =0x8101

  rtn=TDSSend(-1, -1,sf,  0,msg, 0,hd)
  DispData (2,hd, -1,sf,rtn,msg, 0,rtn)

  return rtn


# ------------------------------------------------------------------------------
# S1F2 message (Host) construction and sending ---------------------------------

def SendS1F2H(did,xid):
  global    Md
# hd =SHead()
  hd =(c_ubyte* 12)()
  msg=(c_ubyte*256)();  p_msg=cast(msg,POINTER(c_ubyte))
  sf =0x0102
  ln =0

  val="\0"*32
  
  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    md =tds._TDSMssgInit(      0,p_msg,  256,Fd)            # S1F2
    dmy=tds._TDSMssgBuild(  md,0,p_msg,0o000,  0,  0)       # L0
    ln =tds._TDSMssgEnd(    md,0,p_msg)

  else:                                         # Use message definition
    dmy=tds._TDSMDMssgInit( Md,0,p_msg,  256,b"S1F2_H")
    ln =tds._TDSMDMssgEnd(  Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1,did,sf,xid,msg,ln,hd)

  DispData   (2,hd,did,sf,rtn,msg,ln,rtn)

  return rtn


# ------------------------------------------------------------------------------
# S1F2 message (Equipment) construction and sending ----------------------------

def SendS1F2E(did,xid):
  global    Md
# hd =SHead()
  hd =(c_ubyte* 12)()
  msg=(c_ubyte*256)();  p_msg=cast(msg,POINTER(c_ubyte))
  sf =0x0102
  ln =0

  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    md =tds._TDSMssgInit(     0,p_msg,  256,Fd)             # S1F2
    dmy=tds._TDSMssgBuild( md,0,p_msg,0o000,  2,  0)        # L2
    dmy=tds._TDSMssgBuild( md,0,p_msg,0o020,  6,b"EQUIP1")  #  MDLN
    dmy=tds._TDSMssgBuild( md,0,p_msg,0o020,  6,b"01.000")  #  SOFTREV
    ln =tds._TDSMssgEnd(   md,0,p_msg)

  else:                                         # Use message definition
    dmy=tds._TDSMDMssgInit(Md,0,p_msg,  256,b"S1F2_E")
    ln =tds._TDSMDMssgEnd( Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1,did,sf,xid,msg,ln,hd)

  DispData   (2,hd,did,sf,rtn,msg,ln,rtn)

  return rtn


# ==============================================================================
# S1F21 message construction and sending ---------------------------------------

def SendS1F21():
  global    Md
  hd    =SHead()
# hd    =(c_ubyte  *  12)()
  msg   =(c_ubyte  *4096)();        p_msg =cast(msg,POINTER(c_ubyte))
  zb    =(c_ubyte  *   2)();        vb    =cast(zb ,POINTER(c_ubyte))
  zt    =(c_ubyte  *   2)();        vt    =cast(zt ,POINTER(c_ubyte))
  zs0   =(c_ubyte  *  12)();        vs0   =cast(zs0,c_char_p)
  zs1   =(c_ubyte  *  12)();        vs1   =cast(zs1,c_char_p)
  zs2   =(c_ubyte  *  88)();        vs2   =cast(zs2,c_char_p)
  zi1   =(c_byte   *   2)();        vi1   =cast(zi1,POINTER(c_byte))
  zi2   =(c_short  *   2)();        vi2   =cast(zi2,POINTER(c_short))
  zi4   =(c_int    *   2)();        vi4   =cast(zi4,POINTER(c_int))
  zi8   =(c_int64  *   2)();        vi8   =cast(zi4,POINTER(c_int64))
  zu1   =(c_ubyte  *   2)();        vu1   =cast(zu1,POINTER(c_ubyte))
  zu2   =(c_ushort *   2)();        vu2   =cast(zu2,POINTER(c_ushort))
  zu4   =(c_uint   *   2)();        vu4   =cast(zu4,POINTER(c_uint))
  zu8   =(c_uint64 *   2)();        vu8   =cast(zu8,POINTER(c_uint64))
  yu8   =(c_uint64 *   8)();        au8   =cast(yu8,POINTER(c_uint64))
  zf4   =(c_float  *   2)();        vf4   =cast(zf4,POINTER(c_float))
  zf8   =(c_double *   2)();        vf8   =cast(zf8,POINTER(c_double))
  zdt   =(c_ubyte  * 300)();        fdt   =cast(zdt,POINTER(c_ubyte))

  zb [0]=                      1;   zb [1]=                      0xff
  zt [0]=                      0;   zt [1]=                         1
  vs0   =b"MSG81"
  vs1   ="ｿﾌﾄ 08"                         .encode("SHift_JIS")
  vs2   ="これは ｺﾒﾝﾄ (PythonIo) です"    .encode("SHift_JIS")
  zi1[0]=                      2;   zi1[1]=                      -128
  zi2[0]=                  32767;   zi2[1]=                    -32768
  zi4[0]=             0x7ffffffe;   zi4[1]=                0xfffffffe
  zi8[0]=     0x7fffffffffffffff;   zi8[1]=        0x800080008000800b
  zu1[0]=                   0x7f;   zu1[1]=                      0xff
  zu2[0]=                 0x7ffe;   zu2[1]=                    0xfffe
  zu4[0]=             0x7ffffffd;   zu4[1]=                0xfffffffd
  zu8[0]=     0x7fffffffffffffff;   zu8[1]=        0x800080008000800b
  yu8[0]= 7;  yu8[1]=-6; yu8[2]= 5; yu8[3]=-4
  yu8[4]= 3;  yu8[5]=-2; yu8[6]= 1; yu8[7]= 0
  zf4[0]=         9.87654321e-21;   zf4[1]=           -8.642097531e13
  zf8[0]=-1.9283746574839201e123;   zf8[1]=9.1827364546372819208e-213

  sf =0x8100+21
  ln =0

  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    i=0;            fb=0x20
    while i<300:
      zdt[i]=fb
      if fb==0x7e:  fb=0x20
      else:         fb=fb+1
      i=i+1
    md =        tds._TDSMssgInit(      0,p_msg, 4096,Fd)            # S1F21
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  5,  0)       # L5
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  2,  0)       #  L2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o010,  2,vb )       #   VB
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o011,  2,vt )       #   VT
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  3,  0)       #  L3
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020,  6,vs0)       #   MDLN
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o021,  0,vs1)       #   SOFTREV
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o022,  0,vs2)       #   COMMENT
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  9,  0)       #  L9
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o031,  2,vi1)       #   VI1
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o032,  2,vi2)       #   VI2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o034,  2,vi4)       #   VI4
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o030,  2,vi8)       #   VI8
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o051,  2,vu1)       #   VU1
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o052,  2,vu2)       #   VU2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o054,  2,vu4)       #   VU4
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o050,  2,vu8)       #   VU8
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o050,  8,au8)       #   AU8
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  2,  0)       #  L2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o044,  2,vf4)       #   VF4
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o040,  2,vf8)       #   VF8
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  3,  0)       #  L3
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020,300,fdt)       #   FILETEXT
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o010,300,fdt)       #   FILEBIN
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o052,150,fdt)       #   FILEU2
    ln =        tds._TDSMssgEnd(    md,0,p_msg)

  else:                                         # Use message definition
    pass;       tds._TDSMDMssgInit( Md,0,p_msg,  4096,b"S1F21_HE")
    ln =        tds._TDSMDMssgEnd(  Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1, -1,sf,  0,msg,ln,hd)

  DispData   (2,hd, -1,sf,rtn,msg,ln,rtn)

  return rtn


# ------------------------------------------------------------------------------
# S1F22 message construction and sending ---------------------------------------

def SendS1F22(did,xid):
  global    Md
# hd    =SHead()
  hd    =(c_ubyte  *  12)()
  msg   =(c_ubyte  *4096)();        p_msg =cast(msg,POINTER(c_ubyte))
  zb    =(c_ubyte  *   2)();        vb    =cast(zb ,POINTER(c_ubyte))
  zt    =(c_ubyte  *   2)();        vt    =cast(zt ,POINTER(c_ubyte))
  zs0   =(c_ubyte  *  12)();        vs0   =cast(zs0,c_char_p)
  zs1   =(c_ubyte  *  12)();        vs1   =cast(zs1,c_char_p)
  zs2   =(c_ubyte  *  88)();        vs2   =cast(zs2,c_char_p)
  zi1   =(c_byte   *   2)();        vi1   =cast(zi1,POINTER(c_byte))
  zi2   =(c_short  *   2)();        vi2   =cast(zi2,POINTER(c_short))
  zi4   =(c_int    *   2)();        vi4   =cast(zi4,POINTER(c_int))
  zi8   =(c_int64  *   2)();        vi8   =cast(zi8,POINTER(c_int64))
  zu1   =(c_ubyte  *   2)();        vu1   =cast(zu1,POINTER(c_ubyte))
  zu2   =(c_ushort *   2)();        vu2   =cast(zu2,POINTER(c_ushort))
  zu4   =(c_uint   *   2)();        vu4   =cast(zu4,POINTER(c_uint))
  zu8   =(c_uint64 *   2)();        vu8   =cast(zu8,POINTER(c_uint64))
  yu8   =(c_uint64 *   8)();        au8   =cast(yu8,POINTER(c_uint64))
  zf4   =(c_float  *   2)();        vf4   =cast(zf4,POINTER(c_float))
  zf8   =(c_double *   2)();        vf8   =cast(zf8,POINTER(c_double))

  zb [0]=                      2;   zb [1]=                       0xfe
  zt [0]=                      1;   zt [1]=                          0
  vs0   =b"MSG82"
  vs1   ="ﾚﾋﾞｼﾞｮﾝ"                        .encode("SHift_JIS")
  vs2   ="This is コメント (PythonIo)"    .encode("SHift_JIS")
  zi1[0]=                    127;   zi1[1]=                         -2
  zi2[0]=                  32766;   zi2[1]=                     -32768
  zi4[0]=             2147483646;   zi4[1]=                -2147483647
  zi8[0]=     0x8000000000000000;   zi8[1]=         0x7ffffffffffffffe
  zu1[0]=                    254;   zu1[1]=                       0xff
  zu2[0]=                  65534;   zu2[1]=                     0xffff
  zu4[0]=             4294967294;   zu4[1]=                 0xffffffff
  zu8[0]=   18446744073709551614;   zu8[1]=         0xffffffffffffffff
  yu8[0]=-1;  yu8[1]= 2; yu8[2]=-3; yu8[3]= 4
  yu8[4]=-5;  yu8[5]= 6; yu8[6]=-7; yu8[7]= 0
  zf4[0]=         7.89012345e-12;   zf4[1]=            -4.321098765e31
  zf8[0]= 5.6473829101928374e189;   zf8[1]=-3.2109876543210987654e-179

  sf =0x0100+22
  ln =0
  
  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    md =        tds._TDSMssgInit(      0,p_msg,  256,Fd)            # S1F22
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  4,  0)       # L4
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  2,  0)       #  L2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o010,  2,vb )       #   VB
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o011,  2,vt )       #   VT
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  3,  0)       #  L3
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020,  6,vs0)       #   MDLN
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020,  0,vs1)       #   SOFTREV
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020,  0,vs2)       #   COMMENT
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  9,  0)       #  L9
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o031,  2,vi1)       #   VI1
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o032,  2,vi2)       #   VI2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o034,  2,vi4)       #   VI4
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o030,  2,vi8)       #   VI8
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o051,  2,vu1)       #   VU1
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o052,  2,vu2)       #   VU2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o054,  2,vu4)       #   VU4
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o050,  2,vu8)       #   VU8
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o050,  8,au8)       #   AU8
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  2,  0)       #  L2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o044,  2,vf4)       #   VF4
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o040,  2,vf8)       #   VF8
    ln =        tds._TDSMssgEnd(    md,0,p_msg)

  else:                                         # Use message definition
    pass;       tds._TDSMDMssgInit( Md,0,p_msg,  256,b"S1F22_HE")
    ln =        tds._TDSMDMssgEnd(  Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1,did,sf,xid,msg,ln,hd)

  DispData   (2,hd,did,sf,rtn,msg,ln,rtn)

  return rtn


# ==============================================================================
# S2F49 message construction and sending ---------------------------------------

def SendS2F49():
  global    Md,cnt249
  hd =SHead()
# hd =(c_ubyte*  12)()
  msg=(c_ubyte*4096)(); p_msg=cast(msg,POINTER(c_ubyte))
  val=(c_ubyte*  32)()
  vu1=cast(val,POINTER(c_ubyte))
  vu4=cast(val,POINTER(c_uint))
  sf =0x8200+49
  ln =0

  cnt249+=1
  vst="LOTID ({0:4d})".format(cnt249).encode()
  no1=(cnt249%2)+1; no2=(cnt249%10)+1
  
  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    md =        tds._TDSMssgInit(      0,p_msg, 4096,Fd)            # S2F49
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  3,  0)       # L3
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o010,  1,vu1)       #  DATAIDB
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020,  0,b"LOAD")   #  RCMD
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  4,  0)       #  L4
    vu1[0]=1;   tds._TDSMssgBuild(  md,0,p_msg,0o010,  1,vu1)       #   STID
    vu1[0]=0;   tds._TDSMssgBuild(  md,0,p_msg,0o010,  1,vu1)       #   MTKD
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020, 20,vst)       #   LOTID
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,no1,  0)       #   L[no1]
    i=0
    while i<no1:
      pass;     tds._TDSMssgBuild(  md,0,p_msg,0o000,no2,  0)       #    L[no2]
      j=0
      while j<no2:
        pass;   tds._TDSMssgBuild(  md,0,p_msg,0o000,  2,  0)       #     L[2]
        vst="WAFER({0:04d}-{1:d}-{2:02d})".format(cnt249,i+1,j+1).encode()
        pass;   tds._TDSMssgBuild(  md,0,p_msg,0o020, 20,vst)       #      WAFERID
        vst="PPID ({0:04d}-{1:d}-{2:02d})".format(cnt249,i+1,j+1).encode()
        pass;   tds._TDSMssgBuild(  md,0,p_msg,0o020, 16,vst)       #      PPID
        j+=1
      i+=1
    ln =        tds._TDSMssgEnd(    md,0,p_msg)

  else:                                         # Use message definition
    pass;       tds._TDSMDMssgInit( Md,0,p_msg,  4096,b"S2F49_H")
    pass;       tds._TDSMDMssgBuild(Md,0,p_msg,b"LOTID"  ,0,vst)    #   LOTID
    vu4[0]=no1; tds._TDSMDMssgBuild(Md,0,p_msg,b"NOI1"   ,1,vu4)    #   L[no1]
    i=0
    while i<no1:
      itm   ="NOI2:{0:d}"                 .format(        i+1).encode()
      vu4[0]=no2
      pass;     tds._TDSMDMssgBuild(Md,0,p_msg,itm       ,1,vu4)    #    L[no2]
      j=0
      while j<no2:
        itm="WAFERID:{0:d}:{1:d}"         .format(        i+1,j+1).encode()
        vst="WAFER({0:04d}-{1:d}-{2:02d})".format(cnt249 ,i+1,j+1).encode()
        pass;   tds._TDSMDMssgBuild(Md,0,p_msg,itm        ,0,vst)  #     WAFERID
        itm="PPID:{0:d}:{1:d}"            .format(        i+1,j+1).encode()
        vst="PPID ({0:04d}-{1:d}-{2:02d})".format(cnt249 ,i+1,j+1).encode()
        pass;   tds._TDSMDMssgBuild(Md,0,p_msg,itm        ,0,vst)  #     PPID
        j+=1
      i+=1
    ln =        tds._TDSMDMssgEnd(  Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1, -1,sf,  0,msg,ln,hd)

  DispData   (2,hd, -1,sf,rtn,msg,ln,rtn)

  return rtn


# ------------------------------------------------------------------------------
# S2F50 message construction and sending ---------------------------------------

def SendS2F50(did,xid):
  global    Md,cnt250
# hd =SHead()
  hd =(c_ubyte*  12)()
  msg=(c_ubyte* 256)(); p_msg=cast(msg,POINTER(c_ubyte))
  val=(c_ubyte*  32)()
  vu1=cast(val,POINTER(c_ubyte))
  vu4=cast(val,POINTER(c_uint))
  sf =0x0200+50
  ln =0
  
  cnt250+=1
  vst="LOTID ({0:4d})".format(cnt250).encode()

  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    md =        tds._TDSMssgInit(      0,p_msg,  256,Fd)            # S2F50
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  2,0)         # L2
    vu1[0]=0;   tds._TDSMssgBuild(  md,0,p_msg,0o010,  1,vu1)       #  HCACK
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  2,0)         #  L2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020, 16,b"PPID")   #   PPID
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020, 20,vst)       #   LOTID
    ln =        tds._TDSMssgEnd(    md,0,p_msg)

  else:                                         # Use message definition
    pass;       tds._TDSMDMssgInit( Md,0,p_msg,  256,b"S2F50_E")
    pass;       tds._TDSMDMssgBuild(Md,0,p_msg,b"LOTID",0,vst)      #   LOTID
    ln =        tds._TDSMDMssgEnd(  Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1,did,sf,xid,msg,ln,hd)

  DispData   (2,hd,did,sf,rtn,msg,ln,rtn)

  return rtn


# ==============================================================================
# S6F11 message construction and sending ---------------------------------------

def SendS6F11():
  global    Md,cnt611
  hd =SHead()
# hd =(c_ubyte*  12)()
  msg=(c_ubyte* 256)(); p_msg=cast(msg,POINTER(c_ubyte))
  val=(c_ubyte*  32)()
  vu2=cast(val,POINTER(c_ushort))
  sf =0x8600+11
  ln =0

  cnt611+=1
  if cnt611==65536: cnt611=0

  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    md =        tds._TDSMssgInit(      0,p_msg,  256,Fd)            # S6F11
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  3,0)         # L3
    vu2[0]=cnt611
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o052,  1,vu2)       #  DATAID
    vu2[0]=8;   tds._TDSMssgBuild(  md,0,p_msg,0o052,  1,vu2)       #  CEID
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o000,  3,0)         #  L3
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020, 16,b"DATA1")  #   DATA1
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020, 16,b"DATA2")  #   DATA2
    pass;       tds._TDSMssgBuild(  md,0,p_msg,0o020, 14,b"YYYYMMDDhhmmss")
                        # @TIME Actually I set current time, but omitted.
                        # @TIME (本当は現在時刻を設定するのだが、省略。
    ln =        tds._TDSMssgEnd(    md,0,p_msg)

  else:                                         # Use message definition
    pass;       tds._TDSMDMssgInit( Md,0,p_msg, 256,b"S6F11_E0")
    vu2[0]=cnt611
    pass;       tds._TDSMDMssgBuild(Md,0,p_msg,b"DATAID",1,vu2)     #  DATAID
    ln =        tds._TDSMDMssgEnd(  Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1, -1,sf,  0,msg,ln,hd)

  DispData   (2,hd, -1,sf,rtn,msg,ln,rtn)

  return rtn



# ------------------------------------------------------------------------------
# S6F12 message construction and sending ---------------------------------------

def SendS6F12(did,xid):
  global    Md
# hd =SHead()
  hd =(c_ubyte*  12)()
  msg=(c_ubyte* 256)(); p_msg=cast(msg,POINTER(c_ubyte))
  val=(c_ubyte*  32)()
  vu1=cast(val,POINTER(c_ubyte))
  sf =0x0600+12
  ln =0

  if (MssgUseFile&0x80)==0:                     # Do not use message definition
    md =        tds._TDSMssgInit(      0,p_msg,  256,Fd)        # S6F12
    vu1[0]=0;   tds._TDSMssgBuild(  md,0,p_msg,0o010,  1,vu1)   # ACKC
    ln =        tds._TDSMssgEnd(    md,0,p_msg)

  else:                                         # Use message definition
    pass;       tds._TDSMDMssgInit( Md,0,p_msg,  256,b"S6F12_H")
    ln=         tds._TDSMDMssgEnd(  Md,0,p_msg)

  if ln<0:      rtn=ln
  else:
    rtn=TDSSend(-1,did,sf,xid,msg,ln,hd)

  DispData   (2,hd,did,sf,rtn,msg,ln,rtn)

  return rtn



# ==============================================================================
# Callback function ============================================================

def CBRecvProc(req,rtn,did,xsf,xid,xhd,xmsg):
#   int         req             # i  : Request code to library
#   int         rtn             # i  : Return code from library
#   int         did             # i  : SECS Message Device ID
#   int         xsf             # i  : SECS Message SF-Code
#   int         xid             # i  : SECS Message Transaction I
#   SHead       xhd             # i  : SECS Message Header
#   c_byte      xmsg[]          # i  : SECS Message Body

  global    Fd,Md,OType
  hd =SHead()
# hd =(c_ubyte*  12)(); p_hd =cast(hd ,POINTER(c_ubyte))
  pass;                 p_xhd=cast(xhd,POINTER(c_ubyte))
  msg=(c_ubyte*4096)(); p_msg=cast(msg,POINTER(c_ubyte))
  rnm=(c_ubyte*  32)(); p_rnm=cast(rnm,POINTER(c_char))
  snm=(c_ubyte*  32)(); p_snm=cast(snm,POINTER(c_char))
  sf = c_int(0)
  cmd= c_int(0x0000)

  DispData(1,xhd,did,xsf,xid,xmsg,rtn,rtn)

  if req==0 and rtn>=0:
    if (MssgUseFile&0x80)==0:
                # If you do not use message definition file, check SF-Code on
                # your own, determine necessity of sending secondary message,
                # and send it if necessary.
                # メッセージ定義ファイルを使用しない場合は、自力で SF-Code を
                # 調べ、２次メッセージの送出の必要性を判断し、必要な場合は、
                # 送出する。
      if   xsf==0x8101 and OType==0:    SendS1F2H(did,xid)
      elif xsf==0x8101 and OType==1:    SendS1F2E(did,xid)
      elif xsf==0x8115:                 SendS1F22(did,xid)
      elif xsf==0x8231:                 SendS2F50(did,xid)
      elif xsf==0x860b:                 SendS6F12(did,xid)

    elif  (xsf &0x8000)!=0:
                # When using a message definition file, this sample uses the
                # automatic reply function.
                # メッセージ定義ファイルを使用する場合は、本サンプルでは、自動
                # 返信機能を使用する。
      i=0
      while i<rtn: msg[i]=xmsg[i]; i+=1
      ln=TDSAutoRes(0,xhd,msg,rtn,4096,rnm,snm,sf)
      if  ln>=0:
        rname=cast(rnm,c_char_p).value.decode()
        sname=cast(snm,c_char_p).value.decode()
        print("RECV {0:s} ..  Auto respond {1:s} [S{2:d}F{3:d}]" \
                .format(rname,sname,int(sf.value/0x100),sf.value&0xff))
        rtn=TDSSend(-1,did,sf.value,xid,msg,ln,hd)
        DispData (2,hd,did,sf.value,xid,msg,ln,rtn)
      else:
        if ln!=(-930) and ln!=(-931):
          print("RECV Auto response error ({0:d})".format(ln))

  return 0



# ------------------------------------------------------------------------------

def RecvProcThread():
  global    Fd,Md,Break
# hd =SHead()
  hd =(c_ubyte*  12)();
  msg=(c_ubyte*4096)();
  did= c_int(0)
  xid= c_int(0)
  sf = c_int(0)

  while Break==0:
    req=0
    rtn=TDSRecv(-1,did,sf,xid,msg,4096,hd)
    if rtn==(-951):
      sleep(0.1)
    else:
      if (-1000)<rtn and rtn<(-959):    req=(-rtn)-900
      CBRecvProc(req,rtn,did.value,sf.value,xid.value,hd,msg)



# ==============================================================================
# Host side process ------------------------------------------------------------

def Host():
  global    Fd,Md,Break,OType
# hd =SHead()
  hd =(c_ubyte*  12)(); p_hd =cast(hd ,POINTER(c_ubyte))
  sp =SInfo()
# sp =(c_uint *  16)(); p_sp =cast(sp ,POINTER(c_uint))
  msg=(c_ubyte*4096)(); p_msg=cast(msg,POINTER(c_ubyte))
  did= c_int(0)
  xid= c_int(0)
  sf = c_int(0)

  try:
    OType=0;        Break=0
    if SyncStatus==0:   omd=0x0002
    else:               omd=0x1002
    Fd   =TDSOpen(omd,b"HOST")
    if Fd                                           < 0:    raise ValueError
    print("(H) Opened ({0:d})".format(Fd))
    if (MssgUseFile&0x80)!=0:
      Md=tds._TDSMDMssgInitialize(0x4000,Fd,b"")

    if UseRecvThrd!=0:
      th=threading.Thread(target=RecvProcThread)
      th.start()
 
    if SECS_MODE!=0:
	# In case of HSMS, wait for Select state.
	# For SECS-1 connection, the following connection status confirmation
	# processing may be performed.
	# (Note 1) If connection status is not synchronized with (omd&0x1000)==0
	# at CommOpen() or UDrvOpen(), connection status change report must be
	# received with CommRecv() or UDrvRecv().  (The processing is not
	# described here.)
	# If you are using a receive thread with UseRecvThrd!=0, you don't need,
	# because that thread will receive connection state change reports.
        # (Note 2) In the first place, even if it is not in Selected state, if
	# you think that "_TDSCommSend() etc. will only result in an error
	# (E_ILSEQ)", at least in this AP, this "waiting for Selected state"
	# operation is not necessary.
        #
	# HSMS 接続の場合、Select 状態になるのを待つ。
	# SECS-1 接続の場合も以下の接続ステータス確認処理は行ってもかまわない。
	# (注1) CommOpen()、UDrvOpen() 時に (omd&0x1000)==0 として接続ステータス
	# の同期を行わない場合は、CommRecv()、UDrvRecv() で、接続状態変化報告を
	# 受信しなければならない。
	# UseRecvThrd!=0 で受信スレッドを使用している場合は、そのスレッドにより
	# 接続状態変化報告を受信するので、その必要はない。
        # (注2) そもそも、仮に Selected 状態になっていなくても、「以降の
	# _TDSCommSend() 等がエラー (E_ILSEQ) になるだけ」と考えれば、少なくとも
	# この AP では、この「Selected 状態になるのを待つ」という動作自体が必要
	# ない。
      while True:
        if SyncStatus==0 and UseRecvThrd==0:
          TDSRecv(-1,did,sf,xid,msg,4096,hd)
        rtn=TDSStatus(0)
        if rtn                                      < 0:    raise ValueError
        if rtn                                      ==3:    break
        sleep(0.1)
      print("(H) Selected")

    while True:
      rtn=0
      if UseRecvThrd==0:
        print("Req (0:Exit 1:Recv 2:Send 4:Statistic Report) : "            ,end="")
      else:
        print("Req (0:Exit 2:Send 3:Continuous 4:Statistic Report) : "      ,end="")
      buf=input();          req=int(buf)
      if   req==0:          break

      elif req==1:
        rtn=TDSRecv(-1,did,sf,xid,msg,4096,hd)
        DispData(1,hd,did.value,sf.value,xid.value,msg,rtn,rtn)

      elif req==2:
        if UseRecvThrd==0:
          print("Message(1:S1F1 2:S1F21 3:S2F49  6:S1F2 7:S1F22 8:S6F12) : ",end="")
        else:
          print("Message(1:S1F1 2:S1F21 3:S2F49) : "                        ,end="")
        buf=input();  mno=int(buf)
        if   mno==1:  rtn=SendS1F1( )
        elif mno==2:  rtn=SendS1F21()
        elif mno==3:  rtn=SendS2F49()
        elif mno==6:  rtn=SendS1F2H(did.value,xid.value)
        elif mno==7:  rtn=SendS1F21(did.value,xid.value)
        elif mno==8:  rtn=SendS6F12(did.value,xid.value)

      elif req==3:
        i=0;  Break= 0
        while Break==0:
          sleep(SendWait/1000)
          stat=TDSStatus(0)
          if stat==3:
            rtn=SendS2F49()
            if rtn<0:
              print("(H) Send error ({0:d})".format(rtn))
              sleep(ERROR_SLEEP/1000)
            if (i%SEND_NO)==0:
              sleep(SendSleep  /1000)
        rtn=0

      elif req==4:
        noe=0;  ii=0
        while ii<2:
          print("")
          if   ii==0:
            print("[Sent Primary Message Table]")
          else:
            print("[Received Primary Message Table]")
          print( "   SC  FC: Primary: Second.:Async T3TO: S9F1   F3   F5" \
                 "   F7   F9  F11  F13:  Total.ms (   Ave. ms)")
          s=0
          while s<128:
            f=0
            while f<256:
              rtn=TDSSInfoGet(ii,s*256+f,sp)
              if(rtn    ==0):
                noe=noe+1;      d=f
                if(d!=0):       f=f+1
                nort=sp.nort
                if nort==0:     nort=1
                print("  {0:3d} {1:3d}:{2:8d}:{3:8d}:{4:5d}{5:5d}:{6:5d}{7:5d}{8:5d}"   \
                      "{9:5d}{10:5d}{11:5d}{12:5d}:{13:8d}ms ({14:8.1f}ms)".            \
                    format(s,d  ,sp.nox  ,sp.nort ,sp.norf ,sp.not3                     \
                            ,sp.nof1 ,sp.nof3 ,sp.nof5 ,sp.nof7,sp.nof9                 \
                            ,sp.nof11,sp.nof13,sp.trtok,float(sp.trtok)/float(nort)))
              else:
                if(f    !=0):   f=f+1
              f=f+1
            s=s+1
          ii=ii+1
        if(noe==0):
          print("")
          print("Set STATISINFO=1 in the .ini file when using this function.")
          print("")
        print("")
        rtn=0

      if rtn<(-999) or ((-900)<rtn and rtn<0):
          print("(H) I/O Error ({0:d})".format(rtn))

  except ValueError:    pass
  Break=1
  if Fd>0: TDSClose(0)
  else:
    print("(H) Error ({0:d})".format(Fd))
  if Md>0: tds._TDSMDMssgTerminate(Md,0)



# ==============================================================================
# Equipment side process -------------------------------------------------------

def Equip():
  global    Fd,Md,Break,OType
  hd =SHead()
# hd =(c_ubyte*  12)();
  sp =SInfo()
# sp =(c_uint *  16)(); p_sp =cast(sp ,POINTER(c_uint))
  msg=(c_ubyte*4096)(); p_msg=cast(msg,POINTER(c_ubyte))
  did= c_int(0)
  xid= c_int(0)
  sf = c_int(0)

  try:
    OType=1;            Break=0
    if SyncStatus==0:   omd=0x0002
    else:               omd=0x1002
    Fd   =TDSOpen(omd,b"EQUIP")
    if Fd                                           < 0:    raise ValueError
    print("(E) Opened ({0:d})".format(Fd))
    if (MssgUseFile&0x80)!=0:
      Md=tds._TDSMDMssgInitialize(0x4000,Fd,b"")

    if UseRecvThrd!=0:
      th=threading.Thread(target=RecvProcThread)
      th.start()

    if SECS_MODE!=0 and FuncType==0:    # In case of HSMS and use TDSCommXxxxx()
                                        # HSMS で TDSComm 使用の場合
      if TDSSend(0x0100,-1,0,0,msg,0,hd)            < 0:    raise ValueError
      print("(E) Connected")
      if TDSSend(0x0200,-1,0,0,msg,0,hd)            < 0:    raise ValueError
      print("(E) Select request")

      while True:   # Wait for Select state. See the description for Host().
                    # Select 状態になるのを待つ。 Host() での説明を参照すること。
        if SyncStatus==0 and UseRecvThrd==0:
          TDSRecv(-1,did,sf,xid,msg,4096,hd)
        rtn=TDSStatus(0)
        if rtn                                      < 0:    raise ValueError
        if rtn                                      ==3:    break
        sleep(0.1)
      print("(E) Selected")

    while True:
      rtn=0
      if UseRecvThrd==0:
        print("Req (0:Exit 1:Recv 2:Send 4:Statistic Report) : "            ,end="")
      else:
        print("Req (0:Exit 2:Send 3:Continuous 4:Statistic Report) : "       ,end="")
      buf=input();          req=int(buf)
      if   req==0:          break

      elif req==1:
        rtn=TDSRecv(-1,did,sf,xid,msg,4096,hd)
        DispData (1,hd,did.value,sf.value,xid.value,msg,rtn,rtn)

      elif req==2:
        if UseRecvThrd==0:
          print("Message(1:S1F1 2:S1F21 3:S6F11  6:S1F2 7:S1F22 8:S2F50) : ",end="")
        else:
          print("Message(1:S1F1 2:S1F21 3:S6F11) : "                        ,end="")
        buf=input();  mno=int(buf)
        if   mno==1:  rtn=SendS1F1( )
        elif mno==2:  rtn=SendS1F21()
        elif mno==3:  rtn=SendS6F11()
        elif mno==6:  rtn=SendS1F2E(did.value,xid.value)
        elif mno==7:  rtn=SendS1F22(did.value,xid.value)
        elif mno==8:  rtn=SendS2F50(did.value,xid.value)

      elif req==3:
        i=0;  Break= 0
        while Break==0:
          sleep(SendWait/1000)
          stat=TDSStatus(0)
          if stat==3:
            rtn=SendS6F11()
            if rtn<0:
              print("(E) Send error ({0:d})".format(rtn))
              sleep(ERROR_SLEEP/1000)
            if (i%SEND_NO)==0:
              sleep(SendSleep  /1000)
        rtn=0

      elif req==4:
        noe=0;  ii=0
        while ii<2:
          print("")
          if   ii==0:
            print("[Sent Primary Message Table]")
          else:
            print("[Received Primary Message Table]")
          print( "   SC  FC: Primary: Second.:Async T3TO: S9F1   F3   F5" \
                 "   F7   F9  F11  F13:  Total.ms (   Ave. ms)")
          s=0
          while s<128:
            f=0
            while f<256:
              rtn=TDSSInfoGet(ii,s*256+f,sp)
              if(rtn    ==0):
                noe=noe+1;      d=f
                if(d!=0):       f=f+1
                nort=sp.nort
                if nort==0:     nort=1
                print("  {0:3d} {1:3d}:{2:8d}:{3:8d}:{4:5d}{5:5d}:{6:5d}{7:5d}{8:5d}"   \
                      "{9:5d}{10:5d}{11:5d}{12:5d}:{13:8d}ms ({14:8.1f}ms)".            \
                    format(s,d  ,sp.nox  ,sp.nort ,sp.norf ,sp.not3                     \
                            ,sp.nof1 ,sp.nof3 ,sp.nof5 ,sp.nof7,sp.nof9                 \
                            ,sp.nof11,sp.nof13,sp.trtok,float(sp.trtok)/float(nort)))
              else:
                if(f    !=0):   f=f+1
              f=f+1
            s=s+1
          ii=ii+1
        if(noe==0):
          print("")
          print("Set STATISINFO=1 in the .ini file when using this function.")
          print("")
        print("")
        rtn=0

      if rtn<(-999) or ((-900)<rtn and rtn<0):
          print("(E) I/O Error ({0:d})".format(rtn))

    # If you want to terminate (call _TDSCommClose() or _TDSUDrvClose()) like
    # this AP, you don't need the following "Separate request" processing.
    # この AP の様に、このまま終了する (_TDSCommClose() もしくは _TDSUDrvClose()
    # を Call する) のであれば、以下の "Separate 要求" 処理は必要ない。
    if   SECS_MODE!=0:                      # In case of HSMS, Shutdown process
                                            # HSMS 接続の場合、切断処理
      rtn=TDSStatus(0)
      if rtn==3:
      # Deselect request is not performed. (Of course you may go. However SEMI
      # claims that HSMS-SS does not perform Deselect request.)
      # Deselect request は行わない。 (もちろん行ってもよい。SEMI では HSMS-SS
      # において、Deselect request は行わない、としている。)
      # rtn=TDSSend(0x0800,0,0,0,msg,0,hd)
      # if rtn                                      < 0:    raise ValueError
      # print("(E) Deselected")
        rtn=TDSSend(0x0900,0,0,0,msg,0,hd)
        if rtn                                      < 0:    raise ValueError
        print("(E) Separated")

  except ValueError:    pass
  Break=1
  if Fd>0: TDSClose(0)
  else:
    print("(E) Error ({0:d})".format(Fd))
  if Md>0: tds._TDSMDMssgTerminate(Md,0)



# ==============================================================================
# Main process -----------------------------------------------------------------

opt=0
if FuncType     !=0:            opt|=0x0001
if HeaderBO     !=0:            opt|=0x0002
if MssgDispType !=0x00:         opt|=0x0004
if MssgUseNextL !=0:            opt|=0x0008
if MssgUseFile  !=0x00:         opt|=0x0010
if UseRecvThrd  !=0:            opt|=0x0020
if SyncStatus   !=0:            opt|=0x8000

if len(sys.argv)>2:
  if   sys.argv[2][0:1].lower()=="x":
    opt=int(sys.argv[2][1:],16)
  elif sys.argv[2][0:1]        =="0" and sys.argv[2][1:2].lower()=="x":
    opt=int(sys.argv[2][2:],16)
  else:
    opt=int(sys.argv[2],10)
  if (opt&0x0001)!=0: FuncType    =1
  else:               FuncType    =0
  if (opt&0x0002)!=0: HeaderBO    =1
  else:               HeaderBO    =0
  if (opt&0x0004)!=0: MssgDispType=0x20
  else:               MssgDispType=0x00
  if (opt&0x0008)!=0: MssgUseNextL=1
  else:               MssgUseNextL=0
  if (opt&0x0010)!=0: MssgUseFile =0x80
  else:               MssgUseFile =0x00
  if (opt&0x0020)!=0: UseRecvThrd =1
  else:               UseRecvThrd =0
  if (opt&0x8000)!=0: SyncStatus  =1
  else:               SyncStatus  =0

if len(sys.argv)>3:   SendWait    =int(sys.argv[3],10);
if len(sys.argv)>4:   SendSleep   =int(sys.argv[4],10);

print("option      =0x{0:02x},{1:d}"    .format(opt,opt))
print("FuncType    ={0:d}"              .format(FuncType))
print("HeaderBO    ={0:d}"              .format(HeaderBO))
print("MssgDispType=0x{0:02x}"          .format(MssgDispType))
print("MssgUseNextL={0:d}"              .format(MssgUseNextL))
print("MssgUseFile =0x{0:02x}"          .format(MssgUseFile))
print("UseRecvThrd ={0:d}"              .format(UseRecvThrd))
print("SyncStatus  ={0:d}"              .format(SyncStatus))
print("SendWait    ={0:d}"              .format(SendWait))
print("SendSleep   ={0:d}"              .format(SendSleep))


if len(sys.argv)<2:
  print("")
  print("Usage: python {0:s} {{h|e}} [option [send_wait [send_sleep]]]]".format(sys.argv[0]))
  print("")
  print("  option")
  print("   F           54 3210");
  print("  +----+----+----+----+");
  print("   |           || |||+-- Function to use");
  print("   |           || |||    =0: _TDSCommXxxxx()           1:_TDSUDrvXxxx()");
  print("   |           || ||+--- SECS Header Byte order");
  print("   |           || ||     =0: System order              1: Network order");
  print("   |           || |+---- Format for displaying messages in SECS list format");
  print("   |           || |      =0: TDS Format                1: SML Format");
  print("   |           || +----- Whether to use MssgNextL() for SECS message display");
  print("   |           ||        =0: Not use                   1: Use");
  print("   |           |+------- Whether to use the SECS message definition file");
  print("   |           |         =0: Not use                   1: Use");
  print("   |           +-------- Whether to execute SECS message reception in a dedicated thread");
  print("   |                     =0: No                        1: Yes");
  print("   +-------------------- Synchronize connection status");
  print("                         =0: No                        1: Yes");
  print("  send_wait   : Message sending interval     ({0:d}ms)".format(SendWait))
  print("  send_sleep  : Wait time                    ({0:d}ms)".format(SendSleep))
  print("")
else:
  if sys.argv[1]=="h":  Host( )
  else:                 Equip()
