*-----------------------------------------------------------------------------
* PLC CLIENT: Data Exchange via  TCP/IP (jh.TCPcomm)
*-----------------------------------------------------------------------------
*  Module Deskription
*
*  Start a PLC client to communicate via  TCP-IP with the PLC server.
*  The function Client_Send sends data with the PLC module 9374 to the python script PLC_Client.py .
*  This sends the data to the PLC Server.
*  The server has to answer each data packet inside the timeout time.
*  The answer will be received by the python script and written to the PLC receive structure.
*  The PLC will read out the structure with the module 9373 and call the return function.
*
*  - Announce the send- and receive- structure for the PLC-Python Communication.
*
*  - Start the python script PLC_server.py.
*    Parameter (KS_Process_Parameter):
*      -s:<Name for  the send structure >
*      -r:< Name for  the receive structure >
*      -h:<IP- address or DHCP-Name from the server>
*      -p:<Number of the TCP-IP Port from the server>
*    Example: #define /s KS_Process_Parameter S"-s:STG_PLC_client_transmit -r:STG_PLC_client_receive -h:de01tnc08 -p:8076"
*
*  - Send the data to the connected server.
*
*  - Analysis the incoming data packet and call the return function.
*-----------------------------------------------------------------------------

#define /s    KL_mode_synchronous                      K +0
#define /s    KL_mode_asynchronous                     K +1

#define /s    KL_memory_5_MB                           K +5
#define /s    KL_memory_8_MB                           K +8
#define /s    KL_memory_10_MB                          K +10

#define /s    KL_python_process_active                 K +0
#define /s    KL_python_process_not_active             K +2

#define /s    KL_terminate_python_process              K +0
#define /s    KL_kill_python_process                   K +1
#define /s    KL_ReadByPlc                             K +0
#define /s    KL_WriteByPlc                            K +1
#define /s    KL_Read_Write_status                     K +0
#define /s    KL_wait_for_events                       K -1

#define       KL_No_registered_clients                 K +1
#define       KL_without_wait_overwrite_data           K%000
#define       KL_without_wait                          K +0
#define       KL_with_wait                             K +1
#define       KL_new_data                              K +0

#define       KL_Function_Ping                         K +0
#define       KL_Function_Axis_Positions               K +1
#define       KL_Function_Machine_Status               K +2
#define       KL_function_03                           K +3
#define       KL_function_04                           K +4


#define /s    KS_Process_Path                          S"PLC:\\PYTHON\\PLC_Client.py"
#define /s    KS_Process_parameter                     S"-s:STG_PLC_client_transmit -r:STG_PLC_client_receive -h:160.1.180.8 -p:8076"
#define /s    KS_Process_name                          S"PLC_CLIENT"

#define /s    ML_TCP_IP_client_started                 M
#define /s    ML_Spawn_Receive_started                 M
#define /s    ML_send_started                          M     ;is set for the period of a complete data exchange
#define /s    ML_transmit_release                      M
#define /s    ML_repeat_exit                           M


#define /s    ML_Ping_Server                           M
#define /s    ML_Ping_Server_Ok                        M
#define /s    ML_Axis_Positions                        M
#define /s    ML_Machine_Status                        M
#define /s    ML_function_03                           M
#define /s    ML_function_04                           M

#define /s    BL_Submit_Ident_Start                    B
#define /s    BL_Submit_Ident_Stop                     B
#define /s    BL_submit_ident_monitor                  B
#define /s    BL_return_value                          B
#define /s    BL_transmit_function                     B

#define /s    DL_Error_9295                            D
#define /s    DL_Exit_9295                             D
#define /s    DL_Spawn_receive_Ident                   D
#define /s    DL_function_temp                         D


#include Mac_Lib.inc

GLOBAL TCP_IP_Client

;----------------------------
LBL TCP_IP_Client
;----------------------------

; connection establishment to server

  LN     ML_TCP_IP_client_started
  AN     PN_error_TCP_client_connect_error
  AN     PN_error_submit_spawn_queue_full
  A      MG_pulse_500_ms
  IFT
    RPLY   BL_Submit_Ident_Start
    ==     K+0
    IFT
      SUBM   Client_Start
      =      BL_Submit_Ident_Start
      ==     K+0
      S      PN_error_submit_spawn_queue_full
    ENDI
  ENDI

  L      ML_TCP_IP_client_started
  A      MG_pulse_1_min
  IFT
    RPLY   BL_submit_ident_monitor
    ==     K+0
    IFT
      SUBM   Process_monitor
      =      BL_submit_ident_monitor
      ==     K+0
      S      PN_error_submit_spawn_queue_full
    ENDI
  ENDI

; Python script stop on error

  L      PN_error_TCP_client_connect_error
  A      ML_TCP_IP_client_started
  IFT
    SUBM   Client_Stop
    =      BL_Submit_Ident_Stop
    ==     K+0
    S      PN_error_submit_spawn_queue_full
  ENDI

  L      PN_error_TCP_client_connect_error
  ON     ML_TCP_IP_client_started
  EMT

; Timeout monitoring

  L      DL_function_temp
  >=     K+0
  =      ML_send_started

  LN     ML_send_started
  O      PN_error_TCP_client_connect_error
  =      TS_TCP_IP_client_timeout

  L      ML_send_started
  AN     TR_TCP_IP_client_timeout
  S      PN_error_TCP_client_connect_error

; Client Functionscalls

  REPEAT
    PS     STG_PLC_client_status_transmit.Handle
    PS     KL_Read_Write_status
    CM     9372
    PLW
    ==     K+4                         ; Data have already been collected or not jet provided via module 9374
    =      ML_transmit_release

    L      ML_transmit_release
    IFT
      CASE   BL_transmit_function
        CM     Ping                    ;00
        CM     Axis_Positions          ;01
        CM     Machine_Status          ;02
        CM     Function_03             ;03
        CM     Function_04             ;04
      ENDC

      L      BL_transmit_function
      <      K+4
      IFT
        INC    BL_transmit_function
      ELSE
        L      K+0
        =      BL_transmit_function

        LN     ML_repeat_exit
        S      ML_repeat_exit
      ENDI

    ELSE
      LN     ML_repeat_exit
      S      ML_repeat_exit

    ENDI

    L      ML_repeat_exit
  UNTILT

  L      ML_repeat_exit
  R      ML_repeat_exit

EM

;----------------------------
LBL Client_Start

  ; registration of the PLC structure
  PS     STG_PLC_client_status_transmit.Handle
  PS     KL_Read_Write_status
  CM     9372
  PLW
  <      K+0                           ;invalid handle
  IFT
    PS     S"STG_PLC_client_transmit"
    PS     KL_WriteByPlc
    PS     STG_PLC_client_status_transmit.Event
    CM     9370
    PL     STG_PLC_client_status_transmit.Handle
    PL     STG_PLC_client_status_transmit.LogOnReturn

    M_display_module_error
  ENDI

  PS     STG_PLC_client_status_receive.Handle
  PS     KL_Read_Write_status
  CM     9372
  PLW
  <      K+0                           ;invalid handle
  IFT
    PS     S"STG_PLC_client_receive"
    PS     KL_ReadByPlc
    PS     STG_PLC_client_status_receive.Event
    CM     9370
    PL     STG_PLC_client_status_receive.Handle
    PL     STG_PLC_client_status_receive.LogOnReturn

    M_display_module_error
  ENDI

  ; Python script start
  PS     KS_Process_name
  CM     9297                          ;Status of a Python instance
  PLW
  ==     KL_python_process_active
  IFF
    PS     KL_mode_asynchronous
    PS     KL_memory_8_MB
    PS     KS_Process_Path
    PS     KS_Process_name
    PS     KS_Process_parameter
    CM     9295                        ;Start python process
    PL     DL_Error_9295
    PL     DL_Exit_9295

    M_display_module_error
  ENDI

  ; Start spawn receive
  L      DL_Spawn_receive_Ident
  ==     K+0
  IFT
    SPAWN  Spawn_Client_Receive
    =      DL_Spawn_receive_Ident
    ==     K-1
    S      PN_error_submit_spawn_queue_full
    SN     ML_Spawn_Receive_started
  ENDI

  ; wait for connection
  PS     STG_PLC_client_status_transmit.Handle
  PS     KL_No_registered_clients
  CM     9372
  PLW
  >      K+0
  IFT
    LN     ML_TCP_IP_client_started
    S      ML_TCP_IP_client_started
    S      TS_TCP_IP_client_timeout
  ENDI

  L      K-1
  =      DL_function_temp

EM

;----------------------------
LBL Client_Stop

  L      k-1
  =      DL_function_temp

  PS     KS_Process_name
  CM     9297
  PLW
  ==     KL_python_process_active
  IFT
    PS     KL_terminate_python_process
    PS     KS_Process_name
    CM     9296                        ;Close / interrupt of python instance
    PL     BL_return_value

    M_display_module_error
  ENDI

  L      ML_TCP_IP_client_started
  R      ML_TCP_IP_client_started

EM

;--------------------------------------------------------
; Client Functions
;--------------------------------------------------------
LBL Ping

  L      ML_Ping_Server
  EMF

  L      ML_Ping_Server_Ok
  R      ML_Ping_Server_Ok

  L      KL_Function_Ping
  =      STG_PLC_client_transmit.Function
  CM     Client_Send

  L      ML_Ping_Server
  R      ML_Ping_Server

EM

;----------------------------
LBL Axis_Positions

  L      ML_Axis_Positions
  EMF

  L      KL_Function_Axis_Positions
  =      STG_PLC_client_transmit.Function

  L      DG_position_axis_X_ref
  =      STG_PLC_client_transmit.D_1

  L      DG_position_axis_Y_ref
  =      STG_PLC_client_transmit.D_2

  L      DG_position_axis_Z_ref
  =      STG_PLC_client_transmit.D_3

  CM     Client_Send

  L      ML_Axis_Positions
  R      ML_Axis_Positions

EM

;----------------------------
LBL Machine_Status

  L      ML_Machine_Status
  EMF

  L      KL_Function_Machine_Status
  =      STG_PLC_client_transmit.Function

  CM     Client_Send

  L      ML_Machine_Status
  R      ML_Machine_Status

EM

;----------------------------
LBL Function_03

  L      ML_function_03
  EMF

  L      KL_function_03
  =      STG_PLC_client_transmit.Function

  CM     Client_Send

EM

;----------------------------
LBL Function_04

  L      ML_function_04
  EMF

  L      KL_function_04
  =      STG_PLC_client_transmit.Function

  CM     Client_Send

EM

;----------------------------
LBL Client_Send

  PS     STG_PLC_client_status_transmit.Handle
  PS     KL_without_wait_overwrite_data
  CM     9374
  PL     STG_PLC_client_status_transmit.AccessReturn

  L      STG_PLC_client_status_transmit.AccessReturn
  >      k+0
  S      PN_error_TCP_client_connect_error
  RN     PN_error_TCP_client_connect_error

  L      STG_PLC_client_transmit.Function
  =      DL_function_temp

  ;mce! workaround Client.close doesn't work. Call 62984 !
  L      PN_error_TCP_client_connect_error
  IFT
    RPLY   BL_Submit_Ident_Stop
    ==     K+0
    IFT
      SUBM   Client_Stop
      =      BL_Submit_Ident_Stop
      ==     K+0
      S      PN_error_submit_spawn_queue_full
    ENDI
  ENDI

EM

;--------------------------------------------------------
; Return Functions
;--------------------------------------------------------

; Endless loop for Spawn (wait for Events)
LBL Spawn_Client_Receive

  REPEAT
    PS     STG_PLC_client_status_receive.Handle
    PS     KL_with_wait
    CM     9373
    PL     STG_PLC_client_status_receive.AccessReturn

    CASE   STG_PLC_client_receive.Function
      CM     Ret_Ping                  ;00
      CM     Ret_axis_positions        ;01
      CM     Ret_machine_status        ;02
      CM     Ret_function_03           ;03
      CM     Ret_function_04           ;04
    ENDC

    L      STG_PLC_client_receive.Function
    ==     DL_function_temp
    IFT
      L      K-1
      =      DL_function_temp
    ENDI

    L      STG_PLC_client_status_receive.AccessReturn
    >      K+0
    O      PN_error_submit_spawn_queue_full
    R      ML_Spawn_Receive_started

  UNTILT

  L      K+0
  =      DL_Spawn_receive_Ident
EM

;----------------------------
LBL Ret_Ping

  LN     ML_Ping_Server_Ok
  S      ML_Ping_Server_Ok

EM

;----------------------------
LBL Ret_axis_positions

  L      STG_PLC_client_receive.D_1
  =      STG_PLC_client_receive.D_1

;  L      STG_PLC_Client_Receive.D_2
;  =
;
;  L      STG_PLC_Client_Receive.D_3
;  =

  ; on callback recall positions
  LN     ML_Axis_Positions
  S      ML_Axis_Positions

EM

;----------------------------
LBL Ret_machine_status

  L      STG_PLC_client_receive.M_1
  =      STG_PLC_client_receive.M_1

  L      STG_PLC_client_receive.D_1
  =      STG_PLC_client_receive.D_1

EM

;----------------------------
LBL Ret_function_03

  L      KL_function_03
  =      STG_PLC_client_transmit.Function

EM

;----------------------------
LBL Ret_function_04

  L      KL_function_04
  =      STG_PLC_client_transmit.Function

EM

;----------------------------
LBL Process_monitor

  PS     KS_Process_name
  CM     9297
  PLW
  ==     KL_python_process_not_active
  IFT
    L      MG_marker_one
    R      ML_TCP_IP_client_started
    S      PN_error_TCP_client_connect_error
  ENDI

EM
